remove - ¿Cómo elimino una propiedad de un objeto JavaScript?
remove element from object javascript (30)
Digamos que creo un objeto de la siguiente manera:
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
¿Cuál es la mejor manera de eliminar la propiedad de regex
para terminar con el nuevo myObject
siguiente manera?
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI"
};
2 (ES6)
Para quien lo necesite ...
Para completar la respuesta de @Koen en este hilo, en caso de que quiera eliminar una variable dinámica utilizando la sintaxis de propagación, puede hacerlo así:
const key = ''a'';
const { [key]: foo, ...rest } = { a: 1, b: 2, c: 3 };
console.log(rest); // { b: 2, c: 3 }
* foo
será una nueva variable con el valor de a
(que es 1).
ACTUALIZACIÓN :
hay algunas formas comunes de eliminar una propiedad de un objeto.
Cada uno tiene sus pros y sus contras ( consulte esta comparación de rendimiento ):
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
legible y breve, sin embargo, podría no ser la mejor opción si está operando en una gran cantidad de objetos, ya que su rendimiento no está optimizado.
delete obj[key];
Reassignment
Más de 2 veces más rápido quedelete
, sin embargo, la propiedadno seelimina y se puede iterar.
obj[key] = null;
obj[key] = false;
obj[key] = undefined;
Operador de propagación
EsteES6
operador nos permite devolver un objeto nuevo, excluyendo cualquier propiedad, sin mutar el objeto existente. El inconveniente es que tiene el peor rendimiento de lo anterior y no se sugiere que se use cuando necesite eliminar muchas propiedades a la vez.
{ [key]: val, ...rest } = obj;
Eliminación de propiedad en JavaScript
Hay muchas opciones diferentes presentadas en esta página, no porque la mayoría de las opciones sean incorrectas o porque las respuestas son duplicados, sino porque la técnica adecuada depende de la situación en la que se encuentre y de los objetivos de las tareas en las que usted y / o usted El equipo está tratando de cumplir. Para responder a su pregunta de manera inequívoca, uno necesita saber:
- La versión de ECMAScript que estás apuntando
- El rango de tipos de objetos en los que desea eliminar las propiedades y el tipo de nombres de propiedades que necesita para poder omitir (¿Sólo cadenas? ¿Símbolos? ¿Referencias débiles asignadas desde objetos arbitrarios? Todos estos han sido tipos de punteros de propiedad en JavaScript desde hace años )
- La ética de programación / patrones que usted y su equipo usan. ¿Prefiere los enfoques funcionales y la mutación es verboten en su equipo, o emplea técnicas orientadas a objetos mutativos del salvaje oeste?
- ¿Está buscando lograr esto en JavaScript puro o está dispuesto y puede usar una biblioteca de terceros?
Una vez que se han respondido esas cuatro consultas, hay esencialmente cuatro categorías de "eliminación de propiedades" en JavaScript para elegir a fin de cumplir sus objetivos. Son:
Eliminación de propiedad de objeto mutativo, inseguro
Esta categoría es para operar en literales de objetos o instancias de objetos cuando desea conservar / continuar usando la referencia original y no está utilizando principios funcionales sin estado en su código. Un ejemplo de sintaxis en esta categoría:
''use strict''
const iLikeMutatingStuffDontI = { myNameIs: ''KIDDDDD!'', [Symbol.for(''amICool'')]: true }
delete iLikeMutatingStuffDontI[Symbol.for(''amICool'')] // true
Object.defineProperty({ myNameIs: ''KIDDDDD!'', ''amICool'', { value: true, configurable: false })
delete iLikeMutatingStuffDontI[''amICool''] // throws
Esta categoría es la categoría de eliminación de propiedad más antigua, directa y con mayor respaldo. Admite Symbol
índices de matrices, además de cadenas, y funciona en todas las versiones de JavaScript, excepto en la primera versión. Sin embargo, es mutativo lo que viola algunos principios de programación y tiene implicaciones de rendimiento. También puede dar lugar a excepciones no detectadas cuando se utiliza en developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… .
Omisión de propiedad de cadena basada en el resto
Esta categoría es para operar en objetos simples o en instancias de matriz en versiones más recientes de ECMAScript cuando se desea un enfoque no mutativo y no es necesario tener en cuenta las teclas de símbolos:
const foo = { name: ''KIDDDDD!'', [Symbol.for(''isCool'')]: true }
const { name, ...coolio } = foo // coolio doesn''t have "name"
const { isCool, ...coolio2 } = foo // coolio2 has everything from `foo` because `isCool` doesn''t account for Symbols :(
Supresión de propiedad de objeto mutativo, segura
Esta categoría es para operar en literales de objetos o instancias de objetos cuando desea conservar / continuar usando la referencia original y evitar que se generen excepciones en propiedades no configurables:
''use strict''
const iLikeMutatingStuffDontI = { myNameIs: ''KIDDDDD!'', [Symbol.for(''amICool'')]: true }
Reflect.deleteProperty(iLikeMutatingStuffDontI, Symbol.for(''amICool'')) // true
Object.defineProperty({ myNameIs: ''KIDDDDD!'', ''amICool'', { value: true, configurable: false })
Reflect.deleteProperty(iLikeMutatingStuffDontI, ''amICool'') // false
Además, si bien la mutación de objetos en el lugar no es sin estado, puede utilizar la naturaleza funcional de Reflect.deleteProperty
la aplicación parcial y otras técnicas funcionales que no son posibles con las delete
declaraciones.
Omisión basada en la sintaxis propiedad de la cadena
Esta categoría es para operar en objetos simples o en instancias de matriz en versiones más recientes de ECMAScript cuando se desea un enfoque no mutativo y no es necesario tener en cuenta las teclas de símbolos:
const foo = { name: ''KIDDDDD!'', [Symbol.for(''isCool'')]: true }
const { name, ...coolio } = foo // coolio doesn''t have "name"
const { isCool, ...coolio2 } = foo // coolio2 has everything from `foo` because `isCool` doesn''t account for Symbols :(
Omisión de propiedad basada en la biblioteca
Esta categoría generalmente permite una mayor flexibilidad funcional, incluida la contabilización de símbolos y omitir más de una propiedad en una declaración:
const o = require("lodash.omit")
const foo = { [Symbol.for(''a'')]: ''abc'', b: ''b'', c: ''c'' }
const bar = o(foo, ''a'') // "''a'' undefined"
const baz = o(foo, [ Symbol.for(''a''), ''b'' ]) // Symbol supported, more than one prop at a time, "Symbol.for(''a'') undefined"
Object.assign () & Object.keys () & Array.map ()
const obj = {
"Filters":[
{
"FilterType":"between",
"Field":"BasicInformationRow.A0",
"MaxValue":"2017-10-01",
"MinValue":"2017-09-01",
"Value":"Filters value"
}
]
};
let new_obj1 = Object.assign({}, obj.Filters[0]);
let new_obj2 = Object.assign({}, obj.Filters[0]);
/*
// old version
let shaped_obj1 = Object.keys(new_obj1).map(
(key, index) => {
switch (key) {
case "MaxValue":
delete new_obj1["MaxValue"];
break;
case "MinValue":
delete new_obj1["MinValue"];
break;
}
return new_obj1;
}
)[0];
let shaped_obj2 = Object.keys(new_obj2).map(
(key, index) => {
if(key === "Value"){
delete new_obj2["Value"];
}
return new_obj2;
}
)[0];
*/
// new version!
let shaped_obj1 = Object.keys(new_obj1).forEach(
(key, index) => {
switch (key) {
case "MaxValue":
delete new_obj1["MaxValue"];
break;
case "MinValue":
delete new_obj1["MinValue"];
break;
default:
break;
}
}
);
let shaped_obj2 = Object.keys(new_obj2).forEach(
(key, index) => {
if(key === "Value"){
delete new_obj2["Value"];
}
}
);
¡La delete
operador es inesperadamente lenta!
Mira el benchmark .
Eliminar es la única forma verdadera de eliminar las propiedades del objeto sin restos, pero funciona ~ 100 veces más lento , en comparación con su "alternativa", estableciendo el object[key] = undefined
.
¡Esta alternativa no es la respuesta correcta a esta pregunta! Pero, si lo usa con cuidado, puede acelerar dramáticamente algunos algoritmos. Si está utilizando delete
en bucles y tiene problemas con el rendimiento, lea la explicación detallada.
¿Cuándo se debe usar delete
y cuando se establece un valor como undefined
?
Un objeto puede verse como un conjunto de pares clave-valor. Lo que yo llamo un ''valor'' es una primitiva o una referencia a otro objeto, conectado a esa ''clave''.
Utilice delete
, cuando esté pasando el objeto resultante al código sobre el que no tiene control (o cuando no esté seguro de su equipo o de usted mismo).
Borra la clave del hashmap .
var obj = {
field: 1
};
delete obj.field;
Use la configuración para undefined
, cuando le importa el rendimiento. Puede dar un gran impulso a su código.
La clave permanece en su lugar en el hashmap , solo el valor se reemplaza por undefined
. Comprende, que para for..in
bucle todavía se repetirá sobre esa clave.
var obj = {
field: 1
};
obj.field = undefined;
Usando este método, no todas las formas de determinar la existencia de una propiedad funcionarán como se espera.
Sin embargo, este código:
object.field === undefined
Se comportará de manera equivalente para ambos métodos.
Pruebas
Para resumir, las diferencias tienen que ver con las formas de determinar la existencia de la propiedad, y sobre el bucle for..in
.
console.log(''* -> "Takes prototype inheritance into consideration, that means it lookups all over prototype chain too."'');
console.log(obj.field === undefined, ''obj.field === undefined'', ''You get "undefined" value when querying for "field" in object-hashmap. *'');
console.log(obj["field"] === undefined, ''obj["field"] === undefined'', ''Just another way to query (equivalent). *'');
console.log(typeof obj.field === "undefined", ''typeof obj.field === "undefined"'', ''Get the value attached to "field" key, and check it/'s type is "undefined". *'');
console.log("field" in obj, ''"field" in obj'', ''This statement returns true if "field" key exists in the hashmap. False otherwise. *'');
console.log(obj.hasOwnProperty("field"), ''obj.hasOwnProperty("field")'', ''This statement returns true if /'field/' key exists in the hashmap. The ONLY way NOT to lookup for property in the prototype chain!'');
//Object.keys().indexOf() is an overkill that runs much slower :)
var counter = 0,
key;
for (key in obj) {
counter++;
}
console.assert(counter === 0, ''counter === 0'', ''"field" is not iterated using "for .. in" loop. *'');
¡Cuidado con las fugas de memoria!
Si bien usar obj[prop] = undefined
es más rápido que delete obj[prop]
, otra consideración importante es que obj[prop] = undefined
no siempre es apropiado. delete obj[prop]
elimina prop
de obj
y lo borra de la memoria, mientras que obj[prop] = undefined
simplemente establece el valor de prop
en undefined
que deja a prop
en la memoria. Por lo tanto, en circunstancias donde se crean y eliminan muchas claves, el uso de obj[prop] = undefined
puede forzar una costosa reconciliación de la memoria (lo que provoca que la página se congele) y posiblemente un error de falta de memoria. Examina el siguiente código.
"use strict";
var theNodeList=[], i, current, numberOfNodes=65536, body=document.body, nodeRecords=[];
for (i = 0; i !== numberOfNodes; i++) {
nodeRecords[i] = [];
current = theNodeList[i] = document.createElement("div");
current.textContent = i;
document.body.appendChild( current );
}
var lastTime = -1;
requestAnimationFrame(function recordUpdates(){
var currentTime = Math.round( performance.now()*1000 )
for (i = 0; i !== numberOfNodes; i++) {
if (lastTime !== -1) {
// the previously collected data is no longer in use
/*************************************************/
/****/ nodeRecords[i][lastTime] = undefined; /****/
/*************************************************/
}
nodeRecords[i][currentTime] = theNodeList[i].outerHTML;
}
lastTime = currentTime;
requestAnimationFrame( recordUpdates );
});
En el código anterior, simplemente haciendo nodeRecords[i][lastTime] = undefined;
causará una pérdida de memoria masiva porque cada cuadro de animación. En cada cuadro, todos los 65536 elementos DOM ocuparán otras 65536 ranuras individuales, pero las ranuras 65536 anteriores solo se configurarán como indefinidas, lo que las deja colgadas en la memoria. Adelante, intente ejecutar el código anterior en la consola y ver por sí mismo. Después de forzar un error de memoria insuficiente, intente ejecutarlo nuevamente, excepto con la siguiente versión del código que usa el operador de delete
lugar.
"use strict";
var theNodeList=[], i, current, numberOfNodes=65536, body=document.body, nodeRecords=[];
for (i = 0; i !== numberOfNodes; i++) {
nodeRecords[i] = [];
current = theNodeList[i] = document.createElement("div");
current.textContent = i;
document.body.appendChild( current );
}
var lastTime = -1;
requestAnimationFrame(function recordUpdates(){
var currentTime = Math.round( performance.now()*1000 )
for (i = 0; i !== numberOfNodes; i++) {
if (lastTime !== -1) {
// the previously collected data is no longer in use
/********************************************/
/****/ delete nodeRecords[i][lastTime]; /****/
/********************************************/
}
nodeRecords[i][currentTime] = theNodeList[i].outerHTML;
}
lastTime = currentTime;
requestAnimationFrame( recordUpdates );
});
Como se ve en el fragmento de código anterior, hay algunos casos de uso raros y apropiados para el operador de delete
. Sin embargo, no te preocupes demasiado por este problema. Esto solo se convertirá en un problema con los objetos de larga duración que se agregan constantemente nuevas claves. En cualquier otro caso (que es casi todos los casos en la programación del mundo real), es más apropiado usar obj[prop] = undefined
. El propósito principal de esta sección es solo llamar su atención para que, en la rara ocasión de que esto se convierta en un problema en su código, pueda entender el problema más fácilmente y, por lo tanto, no tenga que perder horas para analizar su código para localizarlo. y entender este problema.
No siempre se establece en undefined
Un aspecto de Javascript que es importante tener en cuenta es el polimorfismo. El polimorfismo es cuando se asignan los mismos tipos de variable / slot-in-an-object como se ve a continuación.
var foo = "str";
foo = 100; // variable foo is now labeled polymorphic by the browser
var bar = ["Some", "example"];
bar[2] = "text"; // bar is a monomorphic array here because all its entries have the
// same type: string primitive
bar[1] = undefined; // bar is now a polymorphic array
Sin embargo, hay dos problemas principales que no se pueden arreglar con matrices polimórficas:
- Son lentos y la memoria ineficiente. Al acceder a un índice específico, en lugar de obtener el tipo global para la matriz, el navegador tiene que obtener el tipo por índice, por lo que cada índice almacena los metadatos adicionales de su tipo.
- Una vez polimórficos, siempre polimórficos. Cuando una matriz se hace polimórfica, el polimorfismo no se puede deshacer en los navegadores Webkit. Por lo tanto, incluso si restaura una matriz polimórfica a no ser polimórfica, el navegador aún la almacenará como una matriz polimórfica.
Uno puede comparar el polimorfismo con una adicción a las drogas. A primera vista, parece asombrosamente lucrativo: un código bonito y esponjoso. Luego, el codificador introduce su matriz al fármaco del polimorfismo. Al instante, la matriz polimórfica se vuelve menos eficiente, y nunca puede volverse tan eficiente como lo era antes, ya que está drogado. Para correlacionar esta circunstancia con la vida real, una persona que consume cocaína podría no ser capaz de operar una simple manija de la puerta, y mucho menos poder calcular los dígitos de PI. Del mismo modo, una matriz sobre el fármaco del polimorfismo nunca puede ser tan eficiente como una matriz monomórfica.
Pero, ¿cómo se relaciona una analogía con el viaje de drogas a la operación de delete
? La respuesta hereda la última línea de código en el fragmento anterior. Por lo tanto, deja que se vuelva a examinar, esta vez con un toque.
var bar = ["Some", "example"];
bar[2] = "text"; // bar is not a polymorphic array here because all its entries have the
// same type: string primitive
bar[1] = ""; // bar is still a monomorphic array
bar[1] = undefined; // bar is now a polymorphic array
Observar. bar[1] = ""
no obliga al polimorfismo, mientras que la bar[1] = undefined
hace. Por lo tanto, siempre debe ser posible, siempre que sea posible, usar el tipo correspondiente para sus objetos para no causar accidentalmente el polimorfismo. Una de esas personas puede usar la siguiente lista como referencia general para ponerla en marcha. Sin embargo, no utilice explícitamente las ideas a continuación. En su lugar, use lo que funcione bien para su código.
- Cuando se usa una matriz / variable escrita en el primitivo booleano, use
false
oundefined
como el valor vacío. Mientras que evitar el polimorfismo innecesario es bueno, reescribir todo el código para prohibirlo de manera explícita probablemente resultará en una disminución en el rendimiento. ¡Usa el juicio común! - Cuando se usa una matriz / variable escrita con el número primitivo, use
0
como el valor vacío. Tenga en cuenta que, internamente, hay dos tipos de números: enteros rápidos (2147483647 a -2147483648 inclusive) y dobles de punto flotante lento (todo lo que incluye aNaN
eInfinity
). Cuando un entero se reduce a un doble, no se puede volver a promover a un entero. - Cuando use una matriz / variable escrita en el primitivo de cadena, use
""
como el valor vacío. - Cuando use un Símbolo, espere, ¿por qué usa un Símbolo?!?! Los símbolos son malos juju para el rendimiento. Todo lo programado para usar Símbolos puede reprogramarse para que no use Símbolos, lo que resulta en un código más rápido sin Símbolos. Los símbolos son realmente meta-azúcar super ineficiente.
- Cuando uses cualquier otra cosa, usa
null
.
Sin embargo, se atento! No comience a hacer esto repentinamente con todo su código preexistente ahora ya que probablemente rompería dicho código preexistente y / o introduciría errores extraños. Más bien, tal práctica eficiente debe implementarse desde el principio, y al convertir el código preexistente, se recomienda que doble, triple, cuádruple verifique todas las líneas relacionadas con eso, ya que tratar de actualizar el código antiguo a esta nueva práctica puede ser tan Riesgo ya que es gratificante.
El término que ha usado en el título de su pregunta Remove a property from a JavaScript object
, puede interpretarse de diferentes maneras. La primera es eliminarla por completo de la memoria y la lista de claves de objeto o la otra es eliminarla de su objeto. Como se ha mencionado en algunas otras respuestas, la palabra clave de delete
es la parte principal. Digamos que tienes tu objeto como:
myJSONObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
Si lo haces:
console.log(Object.keys(myJSONObject));
El resultado sería:
["ircEvent", "method", "regex"]
Puede eliminar esa clave específica de sus claves de objeto como:
delete myJSONObject["regex"];
Entonces su clave de objetos usando Object.keys(myJSONObject)
sería:
["ircEvent", "method"]
Pero el punto es que si le importa la memoria y desea que el objeto se elimine de la memoria, se recomienda establecerlo en nulo antes de eliminar la clave:
myJSONObject["regex"] = null;
delete myJSONObject["regex"];
El otro punto importante aquí es tener cuidado con sus otras referencias al mismo objeto. Por ejemplo, si creas una variable como:
var regex = myJSONObject["regex"];
O agregarlo como un nuevo puntero a otro objeto como:
var myOtherObject = {};
myOtherObject["regex"] = myJSONObject["regex"];
Entonces, incluso si lo elimina de su objeto myJSONObject
, ese objeto específico no se eliminará de la memoria, ya que la variable regex
y myOtherObject["regex"]
aún tienen sus valores. Entonces, ¿cómo podríamos eliminar el objeto de la memoria con seguridad?
La respuesta sería eliminar todas las referencias que tiene en su código, apuntadas a ese mismo objeto y no usar las declaraciones var
para crear nuevas referencias a ese objeto . Este último punto con respecto a las declaraciones var
, es uno de los problemas más cruciales con los que nos enfrentamos habitualmente, porque el uso de las declaraciones var
evitaría que el objeto creado se elimine.
Lo que significa que en este caso no podrá eliminar ese objeto porque ha creado la variable regex
través de una declaración var
, y si lo hace:
delete regex; //False
El resultado sería false
, lo que significa que su declaración de eliminación no se ha ejecutado como esperaba. Pero si no había creado esa variable anteriormente, y solo tenía myOtherObject["regex"]
como su última referencia existente, podría haberlo hecho simplemente eliminándolo como:
myOtherObject["regex"] = null;
delete myOtherObject["regex"];
En otras palabras, un objeto JavaScript se anula tan pronto como no queda ninguna referencia en su código que apunta a ese objeto.
Actualización: Gracias a @AgentME:
Establecer una propiedad en nulo antes de eliminarlo no logra nada (a menos que Object.seal haya sellado el objeto y se produzca un error en la eliminación. Ese no suele ser el caso a menos que lo intente específicamente).
Para obtener más información sobre Object.seal
: Object.seal()
Me gusta esto:
delete myObject.regex;
// or,
delete myObject[''regex''];
// or,
var prop = "regex";
delete myObject[prop];
Manifestación
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
delete myObject.regex;
console.log(myObject);
Para cualquier persona interesada en leer más sobre esto, el usuario de , kangax ha escrito una kangax increíblemente en profundidad sobre la declaración de delete
en su blog, Entendiendo la eliminación . Es muy recomendable.
Otra alternativa es usar la biblioteca Underscore.js .
Tenga en cuenta que _.pick()
y _.omit()
devuelven una copia del objeto y no modifican directamente el objeto original. Asignar el resultado al objeto original debe hacer el truco (no se muestra).
Referencia: link _.pick (objeto, * claves)
Devuelva una copia del objeto, filtrada para que solo tenga valores para las claves en lista blanca (o matriz de claves válidas).
var myJSONObject =
{"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
_.pick(myJSONObject, "ircEvent", "method");
=> {"ircEvent": "PRIVMSG", "method": "newURI"};
Referencia: link _.omit (objeto, * claves)
Devuelva una copia del objeto, filtrada para omitir las claves de la lista negra (o la matriz de claves).
var myJSONObject =
{"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
_.omit(myJSONObject, "regex");
=> {"ircEvent": "PRIVMSG", "method": "newURI"};
Para matrices, _.filter()
y _.reject()
se pueden utilizar de una manera similar.
Prueba esto
delete myObject[''key''];
Vieja pregunta, respuesta moderna. Usando la desestructuración de objetos, una característica ECMAScript 6 , es tan simple como:
const { a, ...rest } = { a: 1, b: 2, c: 3 };
O con la muestra de preguntas:
const myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
const { regex, ...newObject } = myObject;
console.log(newObject);
Puedes verlo en acción en el editor de prueba de Babel.
Editar:
Para reasignar a la misma variable, use un let
:
let myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
({ regex, ...myObject } = myObject);
console.log(myObject);
Actualización 2018-07-21: Durante mucho tiempo, me he sentido avergonzado por esta respuesta, así que creo que es hora de retocarla un poco. Solo un pequeño comentario, aclaración y formato para ayudar a acelerar la lectura de las partes innecesariamente largas y complicadas de esta respuesta.
LA CORTA VERSION
La respuesta real a la pregunta.
Como otros han dicho, puede utilizar delete
.
obj // {"foo": "bar"}
delete obj["foo"]
obj // {}
obj["foo"] // undefined
Array equivalente
No delete
de una matriz. Utilice Array.prototype.splice
lugar.
arr // [1,2,3,4,5]
arr.splice(3,1); // 4
arr // [1,2,3,5]
LA VERSIÓN LARGA
JavaScript es un lenguaje OOP, por lo que todo es un objeto, incluidas las matrices . Por lo tanto, siento que es necesario señalar una advertencia en particular.
En los arreglos, a diferencia de los objetos antiguos, el uso de delete
deja atrás la basura en forma de null
, creando un "agujero" en el arreglo.
var array = [1, 2, 3, 4];
delete array[2];
/* Expected result --> [1, 2, 4]
* Actual result --> [1, 2, null, 4]
*/
Como puede ver, delete
no siempre funciona como uno podría esperar. El valor se sobrescribe, pero la memoria no se reasigna. Es decir, la array[4]
no se reubica en la array[3]
. Lo que contrasta con Array.prototype.unshift
, que inserta un elemento al principio de la matriz y lo desplaza todo hacia arriba (la array[0]
convierte en array[1]
, etc.)
Honestamente, aparte de establecer en null
lugar de undefined
es legítimamente extraño), este comportamiento no debería ser sorprendente, ya que delete
es un operador unario, como typeof
, que está inscrito en el lenguaje y no debe importarle. sobre el tipo de objeto en el que se está utilizando, mientras que Array
es una subclase de Object
con métodos diseñados específicamente para trabajar con matrices. Así que no hay una buena razón para delete
un caso especial preparado para volver a cambiar la matriz, ya que eso solo ralentizaría las cosas con un trabajo innecesario. En retrospectiva, mis expectativas no eran realistas.
Por supuesto, me sorprendió. Porque escribí esto para justificar mi cruzada contra "basura nula":
Ignorando los peligros y problemas inherentes a la
null
y el espacio desperdiciado, esto puede ser problemático si la matriz necesita ser precisa.
Lo que es una terrible justificación para deshacerse de la null
s-- null
solo es peligrosa si se usa incorrectamente, y no tiene nada que ver con la "precisión". La verdadera razón por la que no debe delete
de una matriz es que dejar las estructuras de datos desordenadas y llenas de basura es descuidado y propenso a errores.
Lo que sigue es un escenario artificial que se torna bastante largo, por lo que puede saltar a la sección, La Solución , si lo desea. La única razón por la que dejo esta sección es porque creo que algunas personas probablemente piensan que es gracioso, y no quiero ser "ese tipo" que publica una respuesta "graciosa" y luego borra todo lo "gracioso" más adelante. .
... Es estúpido, lo sé.
El escenario PDP-11 ideado y de largo aliento
Por ejemplo, supongamos que está creando una aplicación web que utiliza la serialización JSON para almacenar una matriz utilizada para "pestañas" en una cadena (en este caso,
localStorage
). Digamos también que el código utiliza los índices numéricos de los miembros de la matriz para "titularlos" al dibujar en la pantalla. ¿Por qué haces esto en lugar de simplemente guardar el "título" también? Porque ... razones .De acuerdo, digamos que está intentando ahorrar memoria a petición de este usuario que ejecuta una minicomputadora PDP-11 desde la década de 1960 que ejecuta UNIX, y escribió su propia impresora de línea basada en Elinks, compatible con JavaScript. navegador porque X11 está fuera de la cuestión .
Dejando de lado cada vez más el estúpido escenario de borde, el uso de
delete
en dicha matriz resultará en una contaminaciónnull
la matriz, y probablemente causará errores en la aplicación más adelante. Y si marcanull
, directamente salteará los números que resulten en que las pestañas se representen como[1] [2] [4] [5] ...
if (array[index] == null) continue; else title = (index + 1).toString(); /* 0 -> "1" * 1 -> "2" * 2 -> (nothing) * 3 -> "4" */
Sí, eso definitivamente no es lo que querías.
Ahora, puede mantener un segundo iterador, como
j
, para incrementar solo cuando se leen valores válidos de la matriz. Pero eso no resolvería exactamente el problemanull
, y todavía tiene que complacer a ese usuario deltrollPDP-11. Por desgracia, su computadora simplemente no tiene suficiente memoria para mantener ese último entero (no pregunte cómo se las arregla para manejar una matriz de ancho variable ...) .Entonces, él te envía un correo electrónico con ira:
Hey, your webapp broke my browser! I checked my localStorage database after your stupid code made my browser segfault, and this is what I found: >"tabs:[''Hello World'', ''foo bar baz'', null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, ... ]" After clearing my precious data, it segfaulted again, and I did a backtrace, and what do I find? WHAT DO I FIND!? YOU USE TOO MANY VARIABLES! >var i = index; >var j = 1; Grr, I am angry now. -Troll Davidson
Acerca de ahora, estás al final de tu ingenio. Este tipo se ha estado quejando sin parar de su aplicación, y usted quiere decirle que se calle y obtenga una computadora mejor.
La Solución: Array.prototype.splice
Afortunadamente, las matrices tienen un método especializado para eliminar índices y reasignar memoria: Array.prototype.splice()
. Podrías escribir algo como esto:
Array.prototype.remove = function(index){
this.splice(index,1);
}
...
array = [1, 2, 3, 4];
array.remove(2);
// Result -> [1, 2, 4]
Y así, ha complacido al Sr. PDP-11. ¡Hurra! (Aun así le regañaría, pero ...)
Array.prototype.splice vs Array.prototype.slice
Creo que es importante señalar la diferencia entre estas dos funciones con nombres similares, ya que ambas son muy útiles.
Array.prototype.splice (inicio, n)
.splice()
muta la matriz y devuelve los índices eliminados. La matriz se divide a partir del índice, el start
y n
elementos se cortan. Si no se especifica n, la matriz completa después del start
se corta ( n = array.length - start
).
let a = [5,4,3,2,1];
let chunk = a.splice(2,2);
// a [5,4,3,2,1]
// start 0 1 2 - -
// n - - 1 2 -
chunk; // [3,2]
a; // [5,4,1]
Array.prototype.slice (inicio, final)
.slice()
no es destructivo y devuelve una nueva matriz que contiene los índices indicados de start
a end
. Si no se especifica el end
, el comportamiento es el mismo que .splice()
( end = array.length
). El comportamiento es un poco complicado ya que, por alguna razón, end
índices de 1 en lugar de 0. No sé por qué lo hace, pero así es. Además, si end <= start
, el resultado es una matriz vacía.
let a = [5,4,3,2,1];
let chunks = [
a.slice(2,0),
a.slice(2,2),
a.slice(2,3),
a.slice(2,5) ];
// a [5,4,3,2,1]
// start 0 1 2 - -
// end, for... - - - - -
// chunks[0] 0 - - - - -
// chunks[1] 1 2 - - -
// chunks[2] 1 2 3 - -
// chunks[3] 1 2 3 4 5
chunks; // [ [], [], [3], [3,2,1] ]
a; // [5,4,3,2,1]
Eso en realidad no es lo que está sucediendo, pero es más fácil pensar de esa manera. Según MDN, esto es lo que realmente está sucediendo:
// a [5,4,3,2,1]
// start 0 1 2 - - -
// end, for... - - - - - -
// chunks[0] 0 - - - - -
// chunks[1] 0 1 2 - - -
// chunks[2] 0 1(2)3 - -
// chunks[3] 0 1(2 3 4)5
El índice especificado por end
es simplemente excluido de la porción. Los índices entre paréntesis indican lo que se corta. De cualquier manera, el comportamiento no es intuitivo y está obligado a causar su parte justa de errores off-by-one, por lo que puede encontrar útil hacer una función de envoltorio para emular más estrechamente el comportamiento de .splice()
:
function ez_slice(array, start = 0, n = null){
if(!Array.isArray(array) || !is_number(start))
return null;
if(is_number(n))
return array.slice(start, start + n);
if(n === null)
return array.slice(start);
return null;
}
ez_slice([5,4,3,2,1], 2, 1) // [3]
ez_slice([5,4,3,2,1], 2) // [3,2,1]
/* Fun fact: isNaN is unreliable.
* [NaN, [], {}, 0, 1, Infinity, undefined, null, "Hi"].filter(isNaN)
* [NaN, {}, undefined, "Hi"]
*
* What we want is...
*
* [NaN, [], {}, 0, 1, Infinity, undefined, null, "Hi"].filter(is_nan)
* [NaN]
*/
function is_nan(num){
return typeof num === "number"
&& num !== num;
}
function is_number(num){
return !is_nan(num)
&& typeof num === "number"
&& isFinite(num);
}
Tenga en cuenta que la función de envoltura está diseñada para ser muy estricta con respecto a los tipos, y devolverá el null
si algo está desactivado. Eso incluye poner una cadena como "3"
. Se deja al programador ser diligente sobre sus tipos. Esto es para fomentar la buena práctica de programación.
Actualización sobre is_array()
Esto es con respecto a este fragmento (ahora eliminado):
function is_array(array){
return array !== null
&& typeof array === "object"
&& typeof array.length !== "undefined"
&& array.__proto__ === Array.prototype;
}
Entonces, resulta que, de hecho, existe una forma integrada de saber si una matriz es realmente una matriz, y esa es Array.isArray()
, introducida en ECMAScript 5 (diciembre de 2009). Encontré esto mientras miraba para ver si había una pregunta que preguntaba acerca de cómo contar arrays de objetos, para ver si había una solución mejor que la mía, o para agregar la mía si no había ninguna. Por lo tanto, si está utilizando una versión de JavaScript anterior a ECMA 5, aquí está su polyfill. Sin embargo, recomiendo encarecidamente que no utilice mi función is_array()
, ya que continuar is_array()
versiones antiguas de JavaScript significa seguir is_array()
los navegadores antiguos que las implementan, lo que significa fomentar el uso de software inseguro y poner a los usuarios en riesgo de malware. Así que por favor, use Array.isArray()
. Usa let
y const
. Utiliza las nuevas funciones que se añaden al lenguaje. No utilice prefijos de proveedores. Eliminar esa basura de polietileno de IE de su sitio web. Elimine ese XHTML <!CDATA[[...
también, nos mudamos a HTML5 en 2014. Cuanto antes todos retiren el soporte para esos navegadores antiguos / esotéricos, más pronto los proveedores de navegadores seguirán el estándar web y adoptarán el estándar Nueva tecnología, y cuanto antes podamos pasar a una web más segura.
Esta publicación es muy antigua y me parece muy útil, así que decidí compartir la función de desarmar que escribí en caso de que alguien más vea esta publicación y piense por qué no es tan simple como en la función de desarmar de PHP.
La razón para escribir esta nueva unset
función es mantener el índice de todas las demás variables en este hash_map. Mire el siguiente ejemplo y vea cómo el índice de "test2" no cambió después de eliminar un valor de hash_map.
function unset(unsetKey, unsetArr, resort){
var tempArr = unsetArr;
var unsetArr = {};
delete tempArr[unsetKey];
if(resort){
j = -1;
}
for(i in tempArr){
if(typeof(tempArr[i]) !== ''undefined''){
if(resort){
j++;
}else{
j = i;
}
unsetArr[j] = tempArr[i];
}
}
return unsetArr;
}
var unsetArr = [''test'',''deletedString'',''test2''];
console.log(unset(''1'',unsetArr,true)); // output Object {0: "test", 1: "test2"}
console.log(unset(''1'',unsetArr,false)); // output Object {0: "test", 2: "test2"}
Hay muchas respuestas buenas aquí, pero solo quiero decir que cuando se usa eliminar para eliminar una propiedad en JavaScript, a menudo es aconsejable verificar primero si esa propiedad existe para evitar errores.
P.ej
var obj = {"property":"value", "property2":"value"};
if (obj && obj.hasOwnProperty("property2")) {
delete obj.property2;
} else {
//error handling
}
Debido a la naturaleza dinámica de JavaScript, a menudo hay casos en los que simplemente no se sabe si la propiedad existe o no. Comprobar si existe obj antes de que && también se asegure de no lanzar un error debido a que se llama a la función hasOwnProperty () en un objeto no definido.
Lo siento si esto no se agregó a su caso de uso específico, pero creo que este es un buen diseño para adaptarse al administrar objetos y sus propiedades.
Hola puedes probar este sencillo y ordenado
var obj = [];
obj.key1 = {name: "John", room: 1234};
obj.key2 = {name: "Jim", room: 1234};
delete(obj.key1);
Muy simple:
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
delete myObject.regex;
Si desea eliminar una propiedad profundamente anidada en el objeto, puede usar la siguiente función recursiva con la ruta a la propiedad como segundo argumento:
var deepObjectRemove = function(obj, path_to_key){
if(path_to_key.length === 1){
delete obj[path_to_key[0]];
return true;
}else{
if(obj[path_to_key[0]])
return deepObjectRemove(obj[path_to_key[0]], path_to_key.slice(1));
else
return false;
}
};
Ejemplo:
var a = {
level1:{
level2:{
level3: {
level4: "yolo"
}
}
}
};
deepObjectRemove(a, ["level1", "level2", "level3"]);
console.log(a);
//Prints {level1: {level2: {}}}
Supongamos que tienes un objeto que se parece a esto:
var Hogwarts = {
staff : [
''Argus Filch'',
''Filius Flitwick'',
''Gilderoy Lockhart'',
''Minerva McGonagall'',
''Poppy Pomfrey'',
...
],
students : [
''Hannah Abbott'',
''Katie Bell'',
''Susan Bones'',
''Terry Boot'',
''Lavender Brown'',
...
]
};
Eliminar una propiedad de objeto
Si desea utilizar la staff
matriz completa , la forma correcta de hacerlo sería hacer esto:
delete Hogwarts.staff;
Alternativamente, también puedes hacer esto:
delete Hogwarts[''staff''];
Del mismo modo, la eliminación de toda la matriz de estudiantes se haría llamando delete Hogwarts.students;
odelete Hogwarts[''students''];
.
Eliminar un índice de matriz
Ahora, si desea eliminar a un solo miembro del personal o estudiante, el procedimiento es un poco diferente, porque ambas propiedades son matrices en sí mismas.
Si conoce el índice de su miembro del personal, simplemente puede hacer esto:
Hogwarts.staff.splice(3, 1);
Si no conoce el índice, también tendrá que hacer una búsqueda de índice:
Hogwarts.staff.splice(Hogwarts.staff.indexOf(''Minerva McGonnagall'') - 1, 1);
Nota
Si bien técnicamente puede usarlo delete
para una matriz, usarlo resultaría en obtener resultados incorrectos cuando llame Hogwarts.staff.length
más adelante, por ejemplo . En otras palabras, delete
eliminaría el elemento, pero no actualizaría el valor de la length
propiedad. Usar delete
también arruinaría tu indexación.
Por lo tanto, cuando elimine valores de un objeto, siempre considere primero si está tratando con las propiedades del objeto o si está tratando con valores de matriz, y elija la estrategia adecuada en función de eso.
Si quieres experimentar con esto, puedes usar este Fiddle como punto de partida.
Usando lodash
import omit from ''lodash/omit'';
const prevObject = {test: false, test2: true};
// Removes test2 key from previous object
const nextObject = omit(prevObject, ''test2'');
Usando Ramda
R.omit([''a'', ''d''], {a: 1, b: 2, c: 3, d: 4}); //=> {b: 2, c: 3}
Utilizando ES6:
(Destructurante + Operador Spread)
const myObject = {
regex: "^http://.*",
b: 2,
c: 3
};
const { regex, ...noRegex } = myObject;
console.log(noRegex); // => { b: 2, c: 3 }
var myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
delete myObject.regex;
console.log ( myObject.regex); // logs: undefined
Esto funciona en Firefox e Internet Explorer, y creo que funciona en todos los demás.
const myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
const { regex, ...other } = myObject;
console.log(myObject)
console.log(regex)
console.log(other)
Considere crear un nuevo objeto sin la "regex"
propiedad porque otras partes de su programa siempre podrían hacer referencia al objeto original. Así debes evitar manipularlo.
const myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
const { regex, ...newMyObject } = myObject;
console.log(newMyObject);
ECMAScript 2015 (o ES6) vino con el objeto Reflect incorporado . Es posible eliminar la propiedad del objeto llamando a la función Reflect.deleteProperty() con el objeto de destino y la clave de propiedad como parámetros:
Reflect.deleteProperty(myJSONObject, ''regex'');
que es equivalente a:
delete myJSONObject[''regex''];
Pero si la propiedad del objeto no es configurable, no se puede eliminar ni con la función deleteProperty ni con el operador de eliminación:
let obj = Object.freeze({ prop: "value" });
let success = Reflect.deleteProperty(obj, "prop");
console.log(success); // false
console.log(obj.prop); // value
Object.freeze() hace que todas las propiedades del objeto no sean configurables (además de otras cosas). deleteProperty
La función (así como el developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ) devuelve false
cuando intenta eliminar cualquiera de sus propiedades. Si la propiedad es configurable, devuelve true
, incluso si la propiedad no existe.
La diferencia entre delete
y deleteProperty
es cuando se usa el modo estricto:
"use strict";
let obj = Object.freeze({ prop: "value" });
Reflect.deleteProperty(obj, "prop"); // false
delete obj["prop"];
// TypeError: property "prop" is non-configurable and can''t be deleted
El developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… es la mejor manera de hacerlo.
Un ejemplo en vivo para mostrar:
var foo = {bar: ''bar''};
delete foo.bar;
console.log(''bar'' in foo); // Logs false, because bar was deleted from foo.
La afirmación de Dan de que ''eliminar'' es muy lenta y se dudó del punto de referencia que publicó. Entonces, yo mismo realicé la prueba en Chrome 59. Parece que ''borrar'' es aproximadamente 30 veces más lento:
var iterationsTotal = 10000000; // 10 million
var o;
var t1 = Date.now(),t2;
for (let i=0; i<iterationsTotal; i++) {
o = {a:1,b:2,c:3,d:4,e:5};
delete o.a; delete o.b; delete o.c; delete o.d; delete o.e;
}
console.log ((t2=Date.now())-t1); // 6135
for (let i=0; i<iterationsTotal; i++) {
o = {a:1,b:2,c:3,d:4,e:5};
o.a = o.b = o.c = o.d = o.e = undefined;
}
console.log (Date.now()-t2); // 205
Tenga en cuenta que, a propósito, realicé más de una operación de ''eliminación'' en un ciclo de bucle para minimizar el efecto causado por las otras operaciones.
Otra solución, utilizando Array#reduce
.
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
myObject = Object.keys(myObject).reduce(function(obj, key) {
if (key != "regex") { //key you want to remove
obj[key] = myObject[key];
}
return obj;
}, {});
console.log(myObject);
Sin embargo, va a mutar el objeto original. Si desea crear un nuevo objeto sin la clave especificada, simplemente asigne la función de reducción a una nueva variable, por ejemplo:
(ES6)
const myObject = {
ircEvent: ''PRIVMSG'',
method: ''newURI'',
regex: ''^http://.*'',
};
const myNewObject = Object.keys(myObject).reduce((obj, key) => {
key !== ''regex'' ? obj[key] = myObject[key] : null;
return obj;
}, {});
console.log(myNewObject);
Personalmente uso Underscore.js para la manipulación de objetos y matrices:
myObject = _.omit(myObject, ''regex'');
Pruebe el siguiente método. Asigne el Object
valor de la propiedad a undefined
. Luego stringify
el objeto y parse
.
var myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
myObject.regex = undefined;
myObject = JSON.parse(JSON.stringify(myObject));
console.log(myObject);
Simplemente puede eliminar cualquier propiedad de un objeto usando la delete
palabra clave.
Por ejemplo:
var obj = {key1:"val1",key2:"val2",key3:"val3"}
Para eliminar cualquier propiedad, digamos key1
, use la delete
palabra clave como esta:
delete obj.key1
O también puedes usar una notación similar a una matriz:
delete obj[key1]
Ref: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… .
Usando ramda#dissoc obtendrá un nuevo objeto sin el atributo regex
:
const newObject = R.dissoc(''regex'', myObject);
// newObject !== myObject
También puede usar otras funciones para lograr el mismo efecto: omitir, seleccionar, ...
Usar el método de eliminación es la mejor manera de hacerlo, según la descripción de MDN, el operador de eliminación elimina una propiedad de un objeto. Así que simplemente puedes escribir:
delete myObject.regex;
// OR
delete myObject[''regex''];
El operador de eliminación elimina una propiedad dada de un objeto. Si se elimina correctamente, devolverá verdadero, de lo contrario se devolverá falso. Sin embargo, es importante tener en cuenta los siguientes escenarios:
Si la propiedad que intenta eliminar no existe, eliminar no tendrá ningún efecto y devolverá verdadero
Si existe una propiedad con el mismo nombre en la cadena de prototipo del objeto, luego de la eliminación, el objeto utilizará la propiedad de la cadena de prototipo (en otras palabras, la eliminación solo tiene un efecto en las propiedades propias).
Cualquier propiedad declarada con var no se puede eliminar del ámbito global o del ámbito de una función.
Como tal, eliminar no puede eliminar ninguna función en el ámbito global (ya sea parte de una definición de función o una función (expresión).
Las funciones que forman parte de un objeto (aparte del
ámbito global) se pueden eliminar con eliminar.Cualquier propiedad declarada con let o const no se puede eliminar del ámbito en el que se definieron. Las propiedades no configurables no se pueden eliminar. Esto incluye propiedades de objetos integrados como Matemáticas, Arreglos, Objetos y propiedades que se crean como no configurables con métodos como Object.defineProperty ().
El siguiente fragmento de código da otro ejemplo simple:
var Employee = {
age: 28,
name: ''abc'',
designation: ''developer''
}
console.log(delete Employee.name); // returns true
console.log(delete Employee.age); // returns true
// When trying to delete a property that does
// not exist, true is returned
console.log(delete Employee.salary); // returns true
Para obtener más información sobre y ver más ejemplos, visite el siguiente enlace: