Digamos que creo un objeto de la siguiente manera:

let myObject = {
    "ircEvent": "PRIVMSG",
    "method": "newURI",
    "regex": "^http://.*"
};

¿Cuál es la mejor manera de eliminar la propiedad regex para terminar con la nueva myObject de la siguiente manera?

let myObject = {
    "ircEvent": "PRIVMSG",
    "method": "newURI"
};
6022
johnstok 16 oct. 2008 a las 14:57

29 respuestas

La mejor respuesta

Así:

delete myObject.regex;
// or,
delete myObject['regex'];
// or,
var prop = "regex";
delete myObject[prop];

Demo

var myObject = {
    "ircEvent": "PRIVMSG",
    "method": "newURI",
    "regex": "^http://.*"
};
delete myObject.regex;

console.log(myObject);

Para cualquier persona interesada en leer más al respecto, el usuario de Stack Overflow kangax ha escrito una publicación de blog increíblemente profunda sobre la {{ X0}} en su blog, Comprensión de la eliminación . Es muy recomendable

8150
Jonathan 9 oct. 2017 a las 16:55

Puede utilizar la desestructuración ES6 con el operador de reposo.

Las propiedades se pueden eliminar utilizando desestructuración en combinación con el operador de descanso . En su ejemplo, la expresión regular se desestructura (se ignora) y el resto de las propiedades se devuelven como descanso.

const noRegex = ({ regex, ...rest }) => rest;
const myObject = {
  "ircEvent": "PRIVMSG",
  "method": "newURI",
  "regex": "^http://.*"
};

console.log(noRegex(myObjext)) //=> {  "ircEvent": "PRIVMSG","method": "newURI" }

O puede excluir dinámicamente propiedades como esta,

const myObject = {
  "ircEvent": "PRIVMSG",
  "method": "newURI",
  "regex": "^http://.*"
};
const removeProperty = prop => ({ [prop]: _, ...rest }) => rest

const removeRegex = removeProperty('regex') //=> {  "ircEvent": "PRIVMSG","method":"newURI" }
const removeMethod = removeProperty('method') //=> {  "ircEvent": "PRIVMSG", "regex":"^http://.*" }
6
Bhargav Patel 10 abr. 2019 a las 20:40

Prueba el siguiente método. Asigne el valor de la propiedad Object 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);
13
Peter Mortensen 22 nov. 2016 a las 22:12

Otra alternativa es utilizar la Underscore.js biblioteca.

Tenga en cuenta que _.pick() y _.omit() ambos devuelven una copia del objeto y no modifican directamente el objeto original. Asignar el resultado al objeto original debería hacer el truco (no se muestra).

Referencia: enlace _.pick (objeto, * teclas)

Devuelve una copia del objeto, filtrada para que solo tenga valores para las claves incluidas en la lista blanca (o conjunto de claves válidas).

var myJSONObject = 
{"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};

_.pick(myJSONObject, "ircEvent", "method");
=> {"ircEvent": "PRIVMSG", "method": "newURI"};

Referencia: enlace _.omit (objeto, * teclas)

Devuelve una copia del objeto, filtrada para omitir las claves incluidas en la lista negra (o conjunto de claves).

var myJSONObject = 
{"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};

_.omit(myJSONObject, "regex");
=> {"ircEvent": "PRIVMSG", "method": "newURI"};

Para las matrices, _.filter() y _.reject() se pueden usar de manera similar.

94
Thaddeus Albers 3 feb. 2018 a las 19:51

Considere crear un nuevo objeto sin la propiedad "regex" porque otras partes de su programa siempre pueden hacer referencia al objeto original. Por lo tanto, debe evitar manipularlo.

const myObject = {
    "ircEvent": "PRIVMSG",
    "method": "newURI",
    "regex": "^http://.*"
};

const { regex, ...newMyObject } = myObject;

console.log(newMyObject);
6
ideaboxer 23 oct. 2017 a las 10:06

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, ...

14
Amio.io 28 nov. 2016 a las 15:14

Esta publicación es muy antigua y me resulta muy útil, así que decidí compartir la función sin configurar 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 sin configurar de PHP.

La razón para escribir esta nueva función unset 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"}
19
Peter Mortensen 22 nov. 2016 a las 21:35

Yo personalmente uso Underscore.js o Lodash para la manipulación de objetos y matrices:

myObject = _.omit(myObject, 'regex');
29
emil 21 ene. 2019 a las 11:24

El operador de eliminación es la mejor manera de hacerlo entonces.

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.
29
Peter Mortensen 11 feb. 2016 a las 20:30

Spread Syntax (ES6)

A quien la necesite ...

Para completar la respuesta @Koen en este hilo, en caso de que desee eliminar la 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(foo);  // 1
console.log(rest); // { b: 2, c: 3 }

* foo será una nueva variable con el valor de a (que es 1).


RESPUESTA EXTENDIDA 😇
Hay pocas formas comunes de eliminar una propiedad de un objeto.
Cada una tiene sus propios pros y contras (verifique esta comparación de rendimiento):

Eliminar operador
Sin embargo, legible y breve, puede que no sea la mejor opción si está operando en una gran cantidad de objetos, ya que su rendimiento no está optimizado.

delete obj[key];


Reasignación
Más de 2 veces más rápido que delete, sin embargo, la propiedad no se elimina y se puede iterar.

obj[key] = null;
obj[key] = false;
obj[key] = undefined;


Operador extendido
Este operador ES6 nos permite devolver un objeto nuevo, excluyendo cualquier propiedad, sin mutar el objeto existente. La desventaja es que tiene el peor rendimiento de lo anterior y no se sugiere su uso cuando necesita eliminar muchas propiedades a la vez.

{ [key]: val, ...rest } = obj;
93
Lior Elrom 18 dic. 2019 a las 15:36

Supongamos que tiene un objeto que se ve así:

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 toda la matriz staff, la forma correcta de hacerlo sería hacerlo:

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 a delete Hogwarts.students; o delete 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 usar delete para una matriz, su uso daría como resultado resultados incorrectos al llamar, por ejemplo, Hogwarts.staff.length más adelante. En otras palabras, delete eliminaría el elemento, pero no actualizaría el valor de la propiedad length. Usar delete también arruinaría tu indexación.

Por lo tanto, al eliminar valores de un objeto, siempre considere primero si se trata de propiedades de objeto o si se trata de valores de matriz, y elija la estrategia adecuada en función de eso.

Si desea experimentar con esto, puede usar este violín como punto de partida.

39
John Slegers 23 nov. 2016 a las 09:17
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.

244
str 1 jun. 2018 a las 16:29

Usando ES6:

(Operadora de desestructuración + propagación)

const myObject = {
    regex: "^http://.*",
    b: 2,
    c: 3
};
const { regex, ...noRegex } = myObject;
console.log(noRegex); // => { b: 2, c: 3 }
36
kalehmann 6 jun. 2019 a las 13:25

Aquí hay muchas buenas respuestas, pero solo quiero decir que cuando use eliminar para eliminar una propiedad en JavaScript, a menudo es aconsejable verificar primero si esa propiedad existe para evitar errores.

E.g

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 sabe si la propiedad existe o no. Comprobar si existe obj antes de && también asegura que no arroje un error debido a llamar a la función hasOwnProperty () en un objeto indefinido.

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.

18
Willem 15 sep. 2014 a las 00:48

Simplemente puede eliminar cualquier propiedad de un objeto utilizando la palabra clave delete.

Por ejemplo:

var obj = {key1:"val1",key2:"val2",key3:"val3"}

Para eliminar cualquier propiedad, diga key1, use la palabra clave delete como esta:

delete obj.key1

O también puede usar la notación tipo matriz:

delete obj[key1]

Ref: MDN.

7
Peter Mortensen 22 nov. 2016 a las 22:11

El uso del método eliminar es la mejor manera de hacerlo, según la descripción de MDN, el operador eliminar elimina una propiedad de un objeto. Entonces simplemente puedes escribir:

delete myObject.regex;
// OR
delete myObject['regex'];

El operador de eliminación elimina una propiedad determinada de un objeto. Al eliminar con éxito, devolverá verdadero, de lo contrario se devolverá falso. Sin embargo, es importante considerar los siguientes escenarios:

  • Si la propiedad que está intentando eliminar no existe, elimine no tendrá ningún efecto y devolverá verdadero

  • Si existe una propiedad con el mismo nombre en el prototipo del objeto cadena, luego, después de la eliminación, el objeto usará la propiedad del cadena de prototipo (en otras palabras, eliminar solo tiene un efecto propio propiedades).

  • Cualquier propiedad declarada con var no se puede eliminar del alcance global o desde el alcance 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).

  • Funciones que forman parte de un objeto (aparte de
    alcance global) se puede eliminar con eliminar.

  • Cualquier propiedad declarada con let o const no se puede eliminar del alcance dentro del cual se definieron. Las propiedades no configurables no se pueden eliminar. Esto incluye propiedades de objetos integrados como Math, Array, Object y propiedades que se crean como no configurables con métodos como Object.defineProperty ().

El siguiente fragmento da otro ejemplo simple:

var Employee = {
      age: 28,
      name: 'Alireza',
      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 y ver más ejemplos, visite el siguiente enlace:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete

25
Alireza 16 abr. 2019 a las 23:22

Object.assign () y Object.keys () y 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"];
        }
    }
);
7
xgqfrms-gildata 10 nov. 2017 a las 06:36

Otra solución, utilizando {{X0} } .

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, 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);
20
kind user 24 oct. 2017 a las 09:58

Prueba esto

delete myObject['key'];
5
codemirror 26 may. 2017 a las 06:58

Hola, puedes probar esto de forma simple

var obj = [];

obj.key1 = {name: "John", room: 1234};
obj.key2 = {name: "Jim", room: 1234};

delete(obj.key1);
5
Gohel Dhaval 26 may. 2017 a las 09:28

La afirmación de Dan de que "eliminar" es muy lenta y se cuestionó el punto de referencia que publicó. Así que realicé la prueba yo mismo en Chrome 59. Parece que 'eliminar' 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 ciclo para minimizar el efecto causado por las otras operaciones.

6
Chong Lip Phang 26 jul. 2017 a las 07:19

¡La operadora delete es inesperadamente lenta!

Mire el punto de referencia .

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", la configuración object[key] = undefined.

¡Esta alternativa no es la respuesta correcta a esta pregunta! Pero, si lo usa con cuidado, puede acelerar drásticamente 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 cuándo se establece el valor en undefined?

Un objeto puede verse como un conjunto de pares clave-valor. Lo que llamo un 'valor' es una primitiva o una referencia a otro objeto, conectado a esa 'clave'.

Use delete, cuando pase el objeto de resultado al código sobre el que no tiene control (o cuando no esté seguro de su equipo o de usted mismo).

elimina la clave del hashmap .

 var obj = {
     field: 1     
 };
 delete obj.field;

Use la configuración en undefined, cuando le interese el rendimiento. Puede dar un gran impulso a su código.

La tecla permanece en su lugar en el hashmap , solo el valor se reemplaza con undefined. Comprenda que el bucle for..in seguirá iterando sobre esa clave.

 var obj = {
     field: 1     
 };
 obj.field = undefined;

Con este método, no todas las formas de determinar la existencia de propiedades funcionará 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 con el ciclo 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 el uso de obj[prop] = undefined es más rápido que el de delete obj[prop], otra consideración importante es que obj[prop] = undefined puede no ser siempre 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 {{X9} } aún en la memoria. Por lo tanto, en circunstancias en las que se crean y eliminan muchas claves, el uso de obj[prop] = undefined puede forzar una costosa reconciliación de memoria (haciendo que la página se congele) y potencialmente 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 hacer nodeRecords[i][lastTime] = undefined; causará una pérdida masiva de memoria porque cada cuadro de animación. Cada cuadro, todos los elementos 65536 DOM ocuparán otros 65536 espacios individuales, pero los 65536 espacios anteriores solo se establecerán en indefinidos, lo que los dejará colgados en la memoria. Siga adelante, intente ejecutar el código anterior en la consola y compruébelo usted mismo. Después de forzar un error de falta de memoria, intente ejecutarlo nuevamente, excepto con la siguiente versión del código que utiliza el operador delete en su 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 apropiados raros para el operador delete. Sin embargo, no te preocupes demasiado por este problema. Esto solo se convertirá en un problema con los objetos de larga vida útil que reciben 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 objetivo principal de esta sección es llamar su atención para que, en la rara posibilidad de que esto se convierta en un problema en su código, pueda comprender más fácilmente el problema y, por lo tanto, no tenga que perder horas diseccionando su código para localizar y entiendo este problema

No establecer siempre en undefined

Un aspecto de Javascript que es importante tener en cuenta es el polimorfismo. El polimorfismo es cuando se asignan diferentes tipos de variables / ranuras en un objeto 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 importantes que no se pueden arreglar con las matrices polimórficas:

  1. Son lentos y la memoria es ineficiente. Al acceder a un índice específico, en lugar de obtener el tipo global para la matriz, el navegador debe obtener el tipo por índice, por lo que cada índice almacena los metadatos adicionales de su tipo.
  2. Una vez polimórfico, siempre polimórfico. Cuando una matriz se hace polimórfica, el polimorfismo no se puede deshacer en los navegadores Webkit. Entonces, incluso si restaura una matriz polimórfica a no polimórfica, el navegador la almacenará como una matriz polimórfica.

Uno puede comparar el polimorfismo con una adicción a las drogas. A primera vista, parece increíblemente lucrativo: un bonito código bastante esponjoso. Luego, el codificador presenta su matriz a la droga del polimorfismo. Al instante, la matriz polimórfica se vuelve menos eficiente, y nunca puede ser tan eficiente como lo era antes, ya que está drogada. Para correlacionar tal circunstancia con la vida real, alguien que toma cocaína podría ni siquiera ser capaz de operar una manija de puerta simple, y mucho menos ser capaz de calcular dígitos de PI. Del mismo modo, una matriz de la droga del polimorfismo nunca puede ser tan eficiente como una matriz monomórfica.

Pero, ¿cómo se relaciona una analogía de viaje de drogas con la operación delete? La respuesta es la última línea de código en el fragmento de arriba. Por lo tanto, que se vuelva a examinar, esta vez con un giro.

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 coacciona el polimorfismo mientras que bar[1] = undefined sí. Por lo tanto, uno siempre debe, siempre que sea posible, usar el tipo correspondiente para sus objetos para no causar polimorfismo accidentalmente. Una de esas personas puede usar la siguiente lista como referencia general para ponerla en marcha. Sin embargo, no utilice explícitamente las siguientes ideas. En su lugar, use lo que funcione bien para su código.

  • Cuando use una matriz / variable escrita en la primitiva booleana, use false o undefined como el valor vacío. Si bien evitar el polimorfismo innecesario es bueno, reescribir todo el código para prohibirlo explícitamente probablemente resulte en una disminución del rendimiento. Use el juicio común!
  • Cuando use una matriz / variable escrita en la primitiva numérica, 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 coma flotante lenta (cualquier otra cosa que no sea NaN y Infinity). Cuando un entero se degrada a un doble, no se puede volver a promocionar a un entero.
  • Cuando use una matriz / variable escrita en la primitiva de cadena, use "" como el valor vacío.
  • Cuando use un símbolo, espere, ¿por qué está usando 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 súper ineficientes.
  • Cuando use cualquier otra cosa, use null.

Sin embargo, ten en cuenta! No empiece de repente a hacer esto con todo su código preexistente ahora, ya que probablemente rompería dicho código preexistente y / o introduciría errores extraños. Por el contrario, una práctica tan eficiente debe implementarse desde el principio, y al convertir el código preexistente, se recomienda que verifique doble, triple y cuádruple todas las líneas relacionadas con eso, ya que intentar actualizar el código antiguo a esta nueva práctica puede ser como arriesgado ya que es gratificante.

929
Community 19 abr. 2018 a las 10:26

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: {}}}
11
ayushgp 23 jun. 2016 a las 09:38
const myObject = {
        "ircEvent": "PRIVMSG",
        "method": "newURI",
        "regex": "^http://.*"
    };

const { regex, ...other } = myObject;

console.log(myObject)
console.log(regex)
console.log(other)
6
xiang 6 feb. 2018 a las 04:28

Vieja pregunta, respuesta moderna. Usando la desestructuración de objetos, una función 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);
182
Koen. 1 dic. 2016 a las 20:51

Para clonar un objeto sin propiedad:

Por ejemplo:

let object = { a: 1, b: 2, c: 3 };   

Y necesitamos eliminar 'a'.

1.Con clave de apoyo explícita:

const { a, ...rest } = object;
object = rest;

2.Con clave de apoyo variable:

const propKey = 'a';
const { [propKey]: propValue, ...rest } = object;
object = rest;

3.Función de flecha fría 😎:

const removePropery = (propKey, { [propKey]: propValue, ...rest }) => rest;

object = removePropery('a', object);

4. Para múltiples propiedades

const removeProperties = (object, ...keys) => Object.entries(object).reduce((prev, [key, value]) => ({...prev, ...(!keys.includes(key) && { [key]: value }) }), {})

Usage

object = removeProperties(object, 'a', 'b') // result => { c: 3 }

Or

    const propsToRemove = ['a', 'b']
    object = removeProperties(object, ...propsToRemove) // result => { c: 3 }
27
YairTawil 23 may. 2019 a las 09:02

ECMAScript 2015 (o ES6) vino con Reflect incorporado. Es posible eliminar la propiedad del objeto llamando a Reflect.deleteProperty () función con objeto de destino y 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 delete:

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). La función deleteProperty (así como eliminar operador) 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
40
madox2 25 ene. 2016 a las 17:22

El término que ha utilizado en el título de su pregunta Remove a property from a JavaScript object puede interpretarse de diferentes maneras. El primero es eliminarlo por completo de la memoria y la lista de claves de objeto o el otro es simplemente eliminarlo de su objeto. Como se ha mencionado en algunas otras respuestas, la palabra clave 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 completar la eliminación del objeto de la memoria, se recomienda configurarlo como 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 crea una variable como:

var regex = myJSONObject["regex"];

O agréguelo 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"] todavía 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, señaló ese mismo objeto y también no usar 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 que generalmente enfrentamos, 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 a través de una instrucció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 antes, y solo tenía myOtherObject["regex"] como su última referencia existente, podría haberlo hecho simplemente eliminándola como:

myOtherObject["regex"] = null;
delete myOtherObject["regex"];

En otras palabras, un objeto JavaScript se elimina tan pronto como no quede ninguna referencia en su código que apunte a ese objeto.


Actualización: Gracias a @AgentME:

Establecer una propiedad como nula antes de eliminarla no logra nada (a menos que Object.seal haya sellado el objeto y la eliminación falle. Ese no suele ser el caso a menos que lo intentes específicamente).

Para obtener más información sobre Object.seal: Object.seal ()

48
Mehran Hatami 2 jun. 2015 a las 22:18

Actualización 2018-07-21: Durante mucho tiempo, me sentí avergonzado por esta respuesta, por lo que creo que es hora de que la retoque 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 VERSIÓN CORTA

La respuesta real a la pregunta.

Como otros han dicho, puedes usar delete.

obj // {"foo": "bar"}
delete obj["foo"]
obj // {}
obj["foo"] // undefined

Array equivalente

No delete de una matriz. Utilice Array.prototype.splice en su lugar.

arr // [1,2,3,4,5]
arr.splice(3,1); // 4
arr // [1,2,3,5]

LA LARGA VERSIÓN

JavaScript es un lenguaje OOP, por lo que todo es un objeto, incluidas matrices . Por lo tanto, siento que es necesario señalar una advertencia particular.

En las matrices, a diferencia de los objetos antiguos simples, el uso de delete deja basura en forma de null, creando un "agujero" en la matriz.

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 cabría esperar. El valor se sobrescribe, pero la memoria no se reasigna. Es decir, array[4] no se reubica en array[3]. Lo que contrasta con Array.prototype.unshift, que inserta un elemento al comienzo de la matriz y desplaza todo hacia arriba (array[0] se convierte en array[1], etc.)

Honestamente, aparte de establecerlo en null en lugar de undefined, lo cual es legítimamente extraño, este comportamiento no debería ser sorprendente, ya que delete es unario operador, como typeof, que está rígido en el lenguaje y no se debe preocupar por el tipo del 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. Por lo tanto, no hay una buena razón para que delete tenga 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 la "basura nula":

Ignorando los peligros y problemas inherentes a null, y el espacio desperdiciado, esto puede ser problemático si la matriz necesita ser precisa.

Lo cual es una justificación terrible para deshacerse de los null s - null solo es peligroso 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 estructuras de datos llenas de basura y desordenadas es descuidado y propenso a errores.

Lo que sigue es un escenario artificial que se alarga bastante, 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 todos los "graciosos" más adelante. .

... Es estúpido, lo sé.

El escenario PDP-11 ideado y 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). Supongamos también que el código usa los índices numéricos de los miembros de la matriz para "titularlos" al dibujar en la pantalla. ¿Por qué haces esto en lugar de solo almacenar el "título" también? Porque ... razones .

De acuerdo, digamos que está tratando de ahorrar memoria a petición de este one usuario que ejecuta una minicomputadora PDP-11 de la década de 1960 con UNIX y escribió su propia versión de Elinks, compatible con JavaScript , navegador de línea amigable con la impresora porque X11 está fuera de cuestión .

Dejando a un lado el escenario de borde cada vez más estúpido, usar delete en dicha matriz resultará en null contaminando la matriz y probablemente causando errores en la aplicación más adelante. Y si marca null, saltará directamente los números, lo que dará como resultado que las pestañas se muestren 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, podría 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 problema de null, y aún debe complacer al usuario de troll PDP-11. Por desgracia, su computadora simplemente no tiene suficiente memoria para contener el ú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

Sobre ahora, estás al final de tu ingenio. Este tipo se ha estado quejando sin parar de tu aplicación, y quieres decirle que se calle y busque una mejor computadora.

La solución: Array.prototype.splice

Afortunadamente, las matrices do 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í, has complacido al Sr. PDP-11. ¡Hurra! (aunque todavía lo delataría ...)

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, start, y los elementos n se dividen. Si n no se especifica, se divide toda la matriz después de start (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, fin)

.slice() no es destructivo y devuelve una nueva matriz que contiene los índices indicados de start a end. Si end se deja sin especificar, el comportamiento es el mismo que .splice() (end = array.length). El comportamiento es un poco complicado ya que, por alguna razón, end indexa desde 1 en lugar de 0. No sé por qué hace esto, pero así es como 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 simplemente se excluye del segmento. Los índices entre paréntesis indican lo que se corta. De cualquier manera, el comportamiento no es intuitivo y está destinado a causar una buena cantidad de errores de uno por uno, por lo que puede resultarle útil hacer una función de envoltura 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 los tipos, y devolverá null si algo está desactivado. Eso incluye poner una cadena como "3". Le corresponde al programador ser diligente con sus tipos. Esto es para fomentar una buena práctica de programación.

Actualización sobre is_array()

Esto se refiere a este fragmento (ahora eliminado):

function is_array(array){
    return array !== null
        && typeof array === "object"
        && typeof array.length !== "undefined"
        && array.__proto__ === Array.prototype;
}

Resulta que, en realidad, hay 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 sobre cómo distinguir las matrices de los 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. Entonces, si está utilizando una versión de JavaScript anterior a ECMA 5, está su polyfill. Sin embargo, recomiendo no usar mi función is_array(), ya que continuar admitiendo versiones antiguas de JavaScript significa continuar admitiendo los navegadores antiguos que los implementan, lo que significa alentar el uso de software inseguro y poner a los usuarios en riesgo de malware. Entonces, por favor, use Array.isArray(). Utilice let y const. Use las nuevas funciones que se agregan al idioma. No use prefijos de proveedor. Eliminar esa basura de IE polyfill de su sitio web. Elimine también esa basura XHTML <!CDATA[[...: nos mudamos a HTML5 en 2014. Cuanto antes todos retiren el soporte para esos navegadores antiguos / esotéricos, antes los proveedores de navegadores seguirán el estándar web y adoptarán la nueva tecnología, y cuanto antes podamos pasar a una web más segura.

209
Braden Best 27 abr. 2019 a las 03:47