¿Cuál es una forma buena y breve de eliminar un valor de un objeto en una clave específica sin alterar el objeto original?
Me gustaría hacer algo como:
let o = {firstname: 'Jane', lastname: 'Doe'};
let o2 = doSomething(o, 'lastname');
console.log(o.lastname); // 'Doe'
console.log(o2.lastname); // undefined
Sé que hay muchas bibliotecas de inmutabilidad para tales tareas, pero me gustaría salirme sin una biblioteca. Pero para hacer esto, un requisito sería tener una forma fácil y corta que pueda usarse en todo el código, sin abstraer el método como una función de utilidad.
Por ejemplo, para agregar un valor, hago lo siguiente:
let o2 = {...o1, age: 31};
Es bastante breve, fácil de recordar y no necesita una función de utilidad.
¿Hay algo como esto para eliminar un valor? ES6 es muy bienvenido.
¡Muchas gracias!
javascript
immutability
amann
fuente
fuente
Respuestas:
Actualizar:
Puede eliminar una propiedad de un objeto con una tarea de Desestructuración complicada :
const doSomething = (obj, prop) => { let {[prop]: omit, ...res} = obj return res }
Sin embargo, si el nombre de propiedad que desea eliminar es estático, puede eliminarlo con una simple línea:
let {lastname, ...o2} = o
La forma más fácil es simplementeO puede clonar su objeto antes de mutarlo:const doSomething = (obj, prop) => { let res = Object.assign({}, obj) delete res[prop] return res }
Alternativamente, puede usar la
omit
función delodash
la biblioteca de utilidades :let o2 = _.omit(o, 'lastname')
Está disponible como parte del paquete lodash o como paquete lodash.omit independiente .
fuente
a2 = a1.filter(el => el.id !== id)
omitir un elemento dentro de una matriz mediante una identificación específica. ¿No existe tal cosa para un objeto?keep_if
const {[prop], ...rest} = obj
funciona? ¿Por qué tiene que asignar la propiedad extraída a una nueva variable (omit
en este caso)?no-unused-vars
regla, es solo una expresión regular.Con la desestructuración de objetos ES7:
const myObject = { a: 1, b: 2, c: 3 }; const { a, ...noA } = myObject; console.log(noA); // => { b: 2, c: 3 }
fuente
a
se almacena en una variableconst x = 'a'
?const { a,b, ...noA } = myObject;
console.log(noA); // => {c: 3 }
solución de una línea
const removeKey = (key, {[key]: _, ...rest}) => rest;
fuente
Como se sugiere en los comentarios anteriores, si desea extender esto para eliminar más de un elemento de su
object
Me gusta usarfilter
. yreduce
p.ej
const o = { "firstname": "Jane", "lastname": "Doe", "middlename": "Kate", "age": 23, "_id": "599ad9f8ebe5183011f70835", "index": 0, "guid": "1dbb6a4e-f82d-4e32-bb4c-15ed783c70ca", "isActive": true, "balance": "$1,510.89", "picture": "http://placehold.it/32x32", "eyeColor": "green", "registered": "2014-08-17T09:21:18 -10:00", "tags": [ "consequat", "ut", "qui", "nulla", "do", "sunt", "anim" ] }; const removeItems = ['balance', 'picture', 'tags'] console.log(formatObj(o, removeItems)) function formatObj(obj, removeItems) { return { ...Object.keys(obj) .filter(item => !isInArray(item, removeItems)) .reduce((newObj, item) => { return { ...newObj, [item]: obj[item] } }, {}) } } function isInArray(value, array) { return array.indexOf(value) > -1; }
fuente
Para agregar un poco de sabor a rendimiento. Compruebe este hilo a continuación
https://github.com/googleapis/google-api-nodejs-client/issues/375
También puedes usar la forma destructiva
const {remov1, remov2, ...new} = old; old = new;
Y un ejemplo más práctico:
this._volumes[this._minCandle] = undefined; { const {[this._minCandle]: remove, ...rest} = this._volumes; this._volumes = rest; }
Como puede ver, puede usar
[somePropsVarForDynamicName]: scopeVarName
sintaxis para nombres dinámicos. Y puede poner todo entre corchetes (nuevo bloque) para que el resto sea basura recolectada después.Aquí una prueba:
ejecutivo:
O podemos ir con alguna función como
function deleteProps(obj, props) { if (!Array.isArray(props)) props = [props]; return Object.keys(obj).reduce((newObj, prop) => { if (!props.includes(prop)) { newObj[prop] = obj[prop]; } return newObj; }, {}); }
para mecanografiar
function deleteProps(obj: Object, props: string[]) { if (!Array.isArray(props)) props = [props]; return Object.keys(obj).reduce((newObj, prop) => { if (!props.includes(prop)) { newObj[prop] = obj[prop]; } return newObj; }, {}); }
Uso:
let a = {propH: 'hi', propB: 'bye', propO: 'ok'}; a = deleteProps(a, 'propB'); // or a = deleteProps(a, ['propB', 'propO']);
De esta forma se crea un nuevo objeto. Y se mantiene la propiedad rápida del objeto. Lo que puede ser importante o importante. Si se accederá al mapeo y al objeto muchas veces.
También asociarse
undefined
puede ser una buena manera de hacerlo. Cuando te lo puedas permitir. Y para las claves, también puede verificar el valor. Por ejemplo, para obtener todas las claves activas, haga algo como:const allActiveKeys = Object.keys(myObj).filter(k => myObj[k] !== undefined); //or const allActiveKeys = Object.keys(myObj).filter(k => myObj[k]); // if any false evaluated value is to be stripped.
Undefined no es adecuado para una lista grande. O desarrollo a lo largo del tiempo con muchos accesorios por venir. Como el uso de la memoria seguirá creciendo y nunca se limpiará. Entonces depende del uso. Y simplemente crear un objeto nuevo parece ser la mejor manera.
Entonces se
Premature optimization is the root of all evil
activará. Por lo tanto, debe ser consciente de la compensación. Y lo que se necesita y lo que no.Nota sobre _.omit () de lodash
Se eliminó de la versión 5. No puede encontrarlo en el repositorio. Y aquí un tema del que hablar.
https://github.com/lodash/lodash/issues/2930
v8
Puede comprobar esto, que es una buena lectura https://v8.dev/blog/fast-properties
fuente
Mi problema con la respuesta aceptada, de un estándar de reglas ESLint, si intenta desestructurar:
const { notNeeded, alsoNotNeeded, ...rest } = { ...ogObject };
las 2 nuevas variables,
notNeeded
yalsoNotNeeded
pueden arrojar una advertencia o error dependiendo de su configuración, ya que ahora no se utilizan. Entonces, ¿por qué crear nuevas vars si no se utilizan?Creo que necesitas usar la
delete
función de verdad.fuente
no-unused-vars
regla tieneignoreRestSiblings
ahora una opción para cubrir este caso de uso: eslint.org/docs/rules/no-unused-vars#ignorerestsiblingscon lodash cloneDeep y eliminar
(nota: el clon lodash se puede usar en su lugar para objetos poco profundos)
const obj = {a: 1, b: 2, c: 3} const unwantedKey = 'a' const _ = require('lodash') const objCopy = _.cloneDeep(obj) delete objCopy[unwantedKey] // objCopy = {b: 2, c: 3}
fuente
Para mi código, quería una versión corta para el valor de retorno de map () pero las soluciones de operaciones multilínea / mutli eran "feas". La característica clave es lo antiguo
void(0)
que se resuelveundefined
.let o2 = {...o, age: 31, lastname: void(0)};
La propiedad permanece en el objeto:
console.log(o2) // {firstname: "Jane", lastname: undefined, age: 31}
pero el marco de transmisión lo mata por mí (bc stringify):
console.log(JSON.stringify(o2)) // {"firstname":"Jane","age":31}
fuente