Supposons que je crée un objet comme suit:

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

Quelle est la meilleure façon de supprimer la propriété regex pour se retrouver avec un nouveau myObject comme suit?

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

29 réponses

Meilleure réponse

Comme ça:

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

Démo

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

console.log(myObject);

Pour quiconque souhaite en savoir plus à ce sujet, l'utilisateur de Stack Overflow kangax a écrit un article de blog incroyablement détaillé sur le {{ X0}} déclaration sur leur blog, Comprendre la suppression . C'est fortement recommandé.

8150
Jonathan 9 oct. 2017 à 16:55

Vous pouvez utiliser la déstructuration ES6 avec l'opérateur de repos.

Les propriétés peuvent être supprimées à l'aide de la déstructuration en combinaison avec l'opérateur de repos . Dans votre exemple, l'expression régulière est déstructurée (ignorée) et le reste des propriétés est renvoyé en tant que reste.

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

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

Ou vous pouvez exclure dynamiquement des propriétés comme celle-ci,

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 avril 2019 à 20:40

Essayez la méthode suivante. Attribuez la valeur de la propriété Object à undefined. Puis stringify l'objet et 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 à 22:12

Une autre alternative consiste à utiliser la bibliothèque Underscore.js.

Notez que _.pick() et _.omit() renvoient tous les deux une copie de l'objet et ne modifient pas directement l'objet d'origine. L'affectation du résultat à l'objet d'origine devrait faire l'affaire (non illustré).

Référence: lien _.pick (objet, * clés)

Renvoie une copie de l'objet, filtrée pour n'avoir que des valeurs pour les clés en liste blanche (ou tableau de clés valides).

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

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

Référence: lien _.omit (objet, * clés)

Renvoie une copie de l'objet, filtrée pour omettre les clés sur liste noire (ou tableau de clés).

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

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

Pour les tableaux, _.filter() et _.reject() peuvent être utilisés de manière similaire.

94
Thaddeus Albers 3 févr. 2018 à 19:51

Envisagez de créer un nouvel objet sans la propriété "regex" car l'objet d'origine pourrait toujours être référencé par d'autres parties de votre programme. Vous devez donc éviter de le manipuler.

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

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

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

En utilisant ramda # dissoc, vous obtiendrez un nouvel objet sans l'attribut regex:

const newObject = R.dissoc('regex', myObject);
// newObject !== myObject

Vous pouvez également utiliser d'autres fonctions pour obtenir le même effet - omettre, choisir, ...

14
Amio.io 28 nov. 2016 à 15:14

Ce message est très ancien et je le trouve très utile, j'ai donc décidé de partager la fonction non définie que j'ai écrite au cas où quelqu'un d'autre verrait ce message et se demander pourquoi ce n'est pas aussi simple que dans la fonction non définie PHP.

La raison de l'écriture de cette nouvelle fonction unset, est de conserver l'index de toutes les autres variables dans cette table de hachage. Regardez l'exemple suivant et voyez comment l'index de "test2" n'a pas changé après avoir supprimé une valeur 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 à 21:35

J'utilise personnellement Underscore.js ou Lodash pour la manipulation d'objets et de tableaux:

myObject = _.omit(myObject, 'regex');
29
emil 21 janv. 2019 à 11:24

supprimer l'opérateur est la meilleure façon de procéder. alors.

Un exemple en direct pour montrer:

var foo = {bar: 'bar'};
delete foo.bar;
console.log('bar' in foo); // Logs false, because bar was deleted from foo.
29
Peter Mortensen 11 févr. 2016 à 20:30

Spread Syntax (ES6)

À qui en a besoin ...

Pour terminer la réponse @Koen dans ce fil, au cas où vous voudriez supprimer une variable dynamique en utilisant la syntaxe étalée, vous pouvez le faire comme ceci:

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 sera une nouvelle variable avec la valeur de a (qui est 1).


RÉPONSE ÉTENDUE 😇
Il existe peu de façons courantes de supprimer une propriété d'un objet.
Chacun a ses avantages et ses inconvénients (vérifiez cette comparaison de performances):

Supprimer l'opérateur
Lisible et court, cependant, il peut ne pas être le meilleur choix si vous travaillez sur un grand nombre d'objets car ses performances ne sont pas optimisées.

delete obj[key];


Réaffectation
Plus de 2 fois plus rapide que delete, cependant la propriété n'est pas supprimée et peut être itérée.

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


Spread Operator
Cet opérateur ES6 nous permet de renvoyer un tout nouvel objet, à l'exclusion de toute propriété, sans muter l'objet existant. L'inconvénient est qu'il a les plus mauvaises performances de ce qui précède et qu'il n'est pas recommandé de l'utiliser lorsque vous devez supprimer de nombreuses propriétés à la fois.

{ [key]: val, ...rest } = obj;
93
Lior Elrom 18 déc. 2019 à 15:36

Supposons que vous ayez un objet qui ressemble à ceci:

var Hogwarts = {
    staff : [
        'Argus Filch',
        'Filius Flitwick',
        'Gilderoy Lockhart',
        'Minerva McGonagall',
        'Poppy Pomfrey',
        ...
    ],
    students : [
        'Hannah Abbott',
        'Katie Bell',
        'Susan Bones',
        'Terry Boot',
        'Lavender Brown',
        ...
    ]
};

Suppression d'une propriété d'objet

Si vous souhaitez utiliser l'intégralité du tableau staff, la bonne façon de procéder serait de procéder comme suit:

delete Hogwarts.staff;

Alternativement, vous pouvez également faire ceci:

delete Hogwarts['staff'];

De même, la suppression de l'ensemble du tableau des étudiants se ferait en appelant delete Hogwarts.students; ou delete Hogwarts['students'];.

Suppression d'un index de tableau

Maintenant, si vous souhaitez supprimer un seul membre du personnel ou étudiant, la procédure est un peu différente, car les deux propriétés sont des tableaux eux-mêmes.

Si vous connaissez l'index de votre membre du personnel, vous pouvez simplement le faire:

Hogwarts.staff.splice(3, 1);

Si vous ne connaissez pas l'index, vous devrez également effectuer une recherche d'index:

Hogwarts.staff.splice(Hogwarts.staff.indexOf('Minerva McGonnagall') - 1, 1);

Remarque

Bien que vous puissiez techniquement utiliser delete pour un tableau, son utilisation entraînerait des résultats incorrects lors de l'appel par exemple Hogwarts.staff.length plus tard. En d'autres termes, delete supprimerait l'élément, mais il ne mettrait pas à jour la valeur de la propriété length. L'utilisation de delete perturberait également votre indexation.

Ainsi, lorsque vous supprimez des valeurs d'un objet, considérez toujours d'abord si vous avez affaire à des propriétés d'objet ou si vous avez affaire à des valeurs de tableau, et choisissez la stratégie appropriée en fonction de cela.

Si vous souhaitez expérimenter cela, vous pouvez utiliser ce violon comme point de départ.

39
John Slegers 23 nov. 2016 à 09:17
var myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
    
delete myObject.regex;

console.log ( myObject.regex); // logs: undefined

Cela fonctionne dans Firefox et Internet Explorer, et je pense que cela fonctionne dans tous les autres.

244
str 1 juin 2018 à 16:29

Utilisation d'ES6:

(Opérateur Destructuration + Spread)

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

Il y a beaucoup de bonnes réponses ici mais je veux juste carillon que lorsque vous utilisez delete pour supprimer une propriété en JavaScript, il est souvent sage de vérifier d'abord si cette propriété existe pour éviter les erreurs.

Par exemple

var obj = {"property":"value", "property2":"value"};

if (obj && obj.hasOwnProperty("property2")) {
  delete obj.property2;
} else {
  //error handling
}

En raison de la nature dynamique de JavaScript, il y a souvent des cas où vous ne savez tout simplement pas si la propriété existe ou non. Vérifier si obj existe avant le && garantit également que vous ne lancez pas d'erreur en raison de l'appel de la fonction hasOwnProperty () sur un objet non défini.

Désolé si cela ne s'ajoute pas à votre cas d'utilisation spécifique, mais je pense que c'est une bonne conception à adapter lors de la gestion des objets et de leurs propriétés.

18
Willem 15 sept. 2014 à 00:48

Vous pouvez simplement supprimer n'importe quelle propriété d'un objet à l'aide du mot clé delete.

Par exemple:

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

Pour supprimer une propriété, dites key1, utilisez le mot clé delete comme ceci:

delete obj.key1

Ou vous pouvez également utiliser une notation de type tableau:

delete obj[key1]

Réf: MDN.

7
Peter Mortensen 22 nov. 2016 à 22:11

L'utilisation de la méthode supprimer est la meilleure façon de le faire, selon la description MDN, l'opérateur de suppression supprime une propriété d'un objet. Vous pouvez donc simplement écrire:

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

L'opérateur de suppression supprime une propriété donnée d'un objet. En cas de suppression réussie, il renverra true, sinon false sera renvoyé. Cependant, il est important de considérer les scénarios suivants:

  • Si la propriété que vous essayez de supprimer n'existe pas, supprimez n'aura aucun effet et retournera vrai

  • Si une propriété du même nom existe sur le prototype de l'objet chaîne, puis, après la suppression, l'objet utilisera la propriété du chaîne de prototype (en d'autres termes, la suppression n'a d'effet que sur propriétés).

  • Aucune propriété déclarée avec var ne peut être supprimée de la portée globale ou de la portée d'une fonction.

  • En tant que tel, delete ne peut supprimer aucune fonction dans la portée globale (que cela fasse partie d'une définition de fonction ou d'une fonction (expression).

  • Fonctions qui font partie d'un objet (en dehors du
    portée globale) peut être supprimé avec suppression.

  • Aucune propriété déclarée avec let ou const ne peut être supprimée de l'étendue dans laquelle elle a été définie. Les propriétés non configurables ne peuvent pas être supprimées. Cela inclut les propriétés des objets intégrés comme Math, Array, Object et les propriétés qui sont créées comme non configurables avec des méthodes comme Object.defineProperty ().

L'extrait de code suivant donne un autre exemple 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

Pour plus d'informations et voir plus d'exemples, visitez le lien ci-dessous:

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

25
Alireza 16 avril 2019 à 23:22

Object.assign () et Object.keys () et 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 à 06:36

Une autre solution, en utilisant {{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);

Cependant, il mute l'objet d'origine. Si vous souhaitez créer un nouvel objet sans la clé spécifiée, affectez simplement la fonction de réduction à une nouvelle variable, par exemple:

(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 à 09:58

Essaye ça

delete myObject['key'];
5
codemirror 26 mai 2017 à 06:58

Bonjour, vous pouvez essayer ce simple tri

var obj = [];

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

delete(obj.key1);
5
Gohel Dhaval 26 mai 2017 à 09:28

L'affirmation de Dan selon laquelle «supprimer» est très lente et la référence qu'il a publiée étaient douteuses. J'ai donc effectué le test moi-même dans Chrome 59. Il semble que "supprimer" soit environ 30 fois plus lent:

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

Notez que j'ai volontairement effectué plus d'une opération de suppression dans un cycle de boucle pour minimiser l'effet provoqué par les autres opérations.

6
Chong Lip Phang 26 juil. 2017 à 07:19

L'opérateur delete est incroyablement lent!

Regardez le benchmark .

La suppression est le seul véritable moyen de supprimer les propriétés d'un objet sans aucun reste, mais cela fonctionne ~ 100 fois plus lentement , par rapport à son "alternative", paramètre object[key] = undefined.

Cette alternative n'est pas la bonne réponse à cette question! Mais, si vous l'utilisez avec précaution, vous pouvez accélérer considérablement certains algorithmes. Si vous utilisez delete dans des boucles et que vous rencontrez des problèmes de performances, lisez l'explication détaillée.

Quand faut-il utiliser delete et quand définir la valeur sur undefined?

Un objet peut être vu comme un ensemble de paires clé-valeur. Ce que j'appelle une «valeur» est une primitive ou une référence à un autre objet, connecté à cette «clé».

Utilisez delete, lorsque vous transmettez l'objet de résultat au code sur lequel vous n'avez aucun contrôle (ou lorsque vous n'êtes pas sûr de votre équipe ou de vous-même).

Il supprime la clé de la table de hachage .

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

Utilisez le paramètre undefined lorsque vous vous souciez des performances. Cela peut donner un sérieux coup de fouet à votre code.

La clé reste à sa place dans la table de hachage , seule la valeur est remplacée par undefined. Comprenez, cette boucle for..in continuera à parcourir cette clé.

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

En utilisant cette méthode, toutes les méthodes de détermination de l'existence d'une propriété ne sont pas toutes fonctionnera comme prévu.

Cependant, ce code:

object.field === undefined

Se comportera de manière équivalente pour les deux méthodes.

Les tests

Pour résumer, les différences concernent toutes les façons de déterminer l'existence d'une propriété et la boucle 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. *');

Méfiez-vous des fuites de mémoire!

Bien que l'utilisation de obj[prop] = undefined soit plus rapide que celle de delete obj[prop], une autre considération importante est que obj[prop] = undefined peut ne pas toujours être approprié. delete obj[prop] supprime prop de obj et l'efface de la mémoire tandis que obj[prop] = undefined définit simplement la valeur de prop à undefined, ce qui laisse {{X9} } toujours en mémoire. Par conséquent, dans les circonstances où de nombreuses clés sont créées et supprimées, l'utilisation de obj[prop] = undefined peut forcer une réconciliation de mémoire coûteuse (provoquant le gel de la page) et potentiellement une erreur de mémoire insuffisante. Examinez le code suivant.

"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 );
});

Dans le code ci-dessus, faire simplement nodeRecords[i][lastTime] = undefined; provoquera une fuite de mémoire massive à cause de chaque image d'animation. Chaque trame, tous les éléments DOM 65536 occuperont un autre 65536 emplacements individuels, mais les emplacements 65536 précédents ne seront définis que sur undefined, ce qui les laissera suspendus dans la mémoire. Allez-y, essayez d'exécuter le code ci-dessus dans la console et voyez par vous-même. Après avoir forcé une erreur de mémoire insuffisante, essayez de l'exécuter à nouveau, sauf avec la version suivante du code qui utilise à la place l'opérateur delete.

"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 );
});

Comme indiqué dans l'extrait de code ci-dessus, il existe de rares cas d'utilisation appropriés pour l'opérateur delete. Cependant, ne vous inquiétez pas trop de ce problème. Cela ne deviendra un problème qu'avec les objets à longue durée de vie qui reçoivent constamment de nouvelles clés. Dans tous les autres cas (ce qui est presque tous les cas dans la programmation du monde réel), il est plus approprié d'utiliser obj[prop] = undefined. Le but principal de cette section est simplement de porter cela à votre attention afin que dans les rares chances que cela devienne un problème dans votre code, vous pourrez alors comprendre plus facilement le problème et ainsi ne pas avoir à perdre des heures à disséquer votre code pour localiser et comprendre ce problème.

Ne pas toujours définir sur undefined

Un aspect de Javascript qui est important à considérer est le polymorphisme. Le polymorphisme consiste à affecter le même type de variable / emplacement dans un objet différent comme indiqué ci-dessous.

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

Cependant, il existe deux problèmes majeurs non résolus avec les tableaux polymorphes:

  1. Ils sont lents et inefficaces en mémoire. Lors de l'accès à un index spécifique, au lieu d'obtenir simplement le type global du tableau, le navigateur doit plutôt obtenir le type par index, chaque index stockant les métadonnées supplémentaires de son type.
  2. Une fois polymorphe, toujours polymorphe. Lorsqu'un tableau est rendu polymorphe, le polymorphisme ne peut pas être annulé dans les navigateurs Webkit. Ainsi, même si vous restaurez un tableau polymorphe à être non polymorphe, il sera toujours stocké par le navigateur en tant que tableau polymorphe.

On peut comparer le polymorphisme à une toxicomanie. À première vue, cela semble extrêmement lucratif: un joli code assez moelleux. Ensuite, le codeur présente leur réseau au médicament du polymorphisme. Instantanément, le réseau polymorphe devient moins efficace, et il ne peut jamais devenir aussi efficace qu'auparavant puisqu'il est drogué. Pour corréler une telle circonstance à la vie réelle, une personne sous cocaïne pourrait même ne pas être capable de faire fonctionner une simple poignée de porte, et encore moins être capable de calculer les chiffres de PI. De même, un tableau sur le médicament du polymorphisme ne peut jamais être aussi efficace qu'un tableau monomorphe.

Mais, comment une analogie de voyage de drogue est-elle liée à l'opération delete? La réponse hérite de la dernière ligne de code de l'extrait ci-dessus. Qu'il soit donc réexaminé, cette fois avec une torsion.

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

Observer. bar[1] = "" ne contraint pas le polymorphisme contrairement à bar[1] = undefined. Par conséquent, il faut toujours, dans la mesure du possible, utiliser le type correspondant pour leurs objets afin de ne pas provoquer accidentellement de polymorphisme. Une de ces personnes peut utiliser la liste suivante comme référence générale pour les mettre en route. Cependant, veuillez ne pas utiliser explicitement les idées ci-dessous. À la place, utilisez tout ce qui fonctionne bien pour votre code.

  • Lorsque vous utilisez un tableau / une variable tapé à la primitive booléenne, utilisez false ou undefined comme valeur vide. Bien qu'il soit bon d'éviter le polymorphisme inutile, réécrire tout votre code pour l'interdire explicitement entraînera probablement une baisse des performances. Utilisez un jugement commun!
  • Lorsque vous utilisez un tableau / une variable tapé à la primitive numérique, utilisez 0 comme valeur vide. Notez qu'en interne, il existe deux types de nombres: les entiers rapides (2147483647 à -2147483648 inclus) et les doubles à virgule flottante lente (tout autre que celui comprenant NaN et Infinity). Lorsqu'un entier est rétrogradé en double, il ne peut pas être promu en entier.
  • Lorsque vous utilisez un tableau / une variable tapé dans la primitive de chaîne, utilisez "" comme valeur vide.
  • Lorsque vous utilisez un symbole, attendez, pourquoi utilisez-vous un symbole?!?! Les symboles sont mauvais juju pour la performance. Tout ce qui est programmé pour utiliser des symboles peut être reprogrammé pour ne pas utiliser de symboles, résultant en un code plus rapide sans symboles. Les symboles sont vraiment du méta-sucre super inefficace.
  • Lorsque vous utilisez autre chose, utilisez null.

Mais attention! Ne commencez pas soudainement à faire cela avec tout votre code préexistant car cela pourrait probablement casser un tel code préexistant et / ou introduire d'étranges bogues. Au contraire, une telle pratique efficace doit être mise en œuvre dès le début, et lors de la conversion de code préexistant, il est recommandé de doubler, tripler, quadrupler vérifier toutes les lignes relatives à cela, car essayer de mettre à niveau l'ancien code vers cette nouvelle pratique peut être aussi risqué car c'est gratifiant.

929
Community 19 avril 2018 à 10:26

Si vous souhaitez supprimer une propriété profondément imbriquée dans l'objet, vous pouvez utiliser la fonction récursive suivante avec chemin d'accès à la propriété comme deuxième argument:

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;
    }
};

Exemple:

var a = {
    level1:{
        level2:{
            level3: {
                level4: "yolo"
            }
        }
    }
};

deepObjectRemove(a, ["level1", "level2", "level3"]);
console.log(a);

//Prints {level1: {level2: {}}}
11
ayushgp 23 juin 2016 à 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 févr. 2018 à 04:28

Vieille question, réponse moderne. En utilisant la déstructuration d'objets, une ECMAScript 6 fonctionnalité, c'est aussi simple que:

const { a, ...rest } = { a: 1, b: 2, c: 3 };

Ou avec l'exemple de questions:

const myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
const { regex, ...newObject } = myObject;
console.log(newObject);

Vous pouvez le voir en action dans l'éditeur d'essai Babel.


Modifier:

Pour réaffecter à la même variable, utilisez un let:

let myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
({ regex, ...myObject } = myObject);
console.log(myObject);
182
Koen. 1 déc. 2016 à 20:51

Pour cloner un objet sans propriété:

Par exemple:

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

Et nous devons supprimer «a».

1. avec clé prop explicite:

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

2. avec clé prop variable:

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

3.Fonction de flèche froide 😎:

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

object = removePropery('a', object);

4. Pour plusieurs propriétés

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

Utilisation

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

Ou

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

ECMAScript 2015 (ou ES6) est livré avec un objet Reflect intégré. Il est possible de supprimer une propriété d'objet en appelant Reflect.deleteProperty () fonction avec objet cible et clé de propriété comme paramètres:

Reflect.deleteProperty(myJSONObject, 'regex');

Ce qui équivaut à:

delete myJSONObject['regex'];

Mais si la propriété de l'objet n'est pas configurable, elle ne peut être supprimée ni avec la fonction deleteProperty ni avec l'opérateur delete:

let obj = Object.freeze({ prop: "value" });
let success = Reflect.deleteProperty(obj, "prop");
console.log(success); // false
console.log(obj.prop); // value

Object.freeze () rend toutes les propriétés de l'objet non configurables (en plus d'autres choses). La fonction deleteProperty (ainsi que supprimer l'opérateur) renvoie false quand essaie de supprimer l'une de ses propriétés. Si la propriété est configurable, elle renvoie true, même si la propriété n'existe pas.

La différence entre delete et deleteProperty réside dans l'utilisation du mode strict:

"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 janv. 2016 à 17:22

Le terme que vous avez utilisé dans le titre de votre question Remove a property from a JavaScript object peut être interprété de différentes manières. L'une consiste à la supprimer pour toute la mémoire et la liste des clés d'objet ou l'autre consiste simplement à la supprimer de votre objet. Comme cela a été mentionné dans d'autres réponses, le mot clé delete est la partie principale. Disons que vous avez votre objet comme:

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

Si tu fais:

console.log(Object.keys(myJSONObject));

Le résultat serait:

["ircEvent", "method", "regex"]

Vous pouvez supprimer cette clé spécifique de vos clés d'objet comme:

delete myJSONObject["regex"];

Votre clé d'objets utilisant Object.keys(myJSONObject) serait alors:

["ircEvent", "method"]

Mais le fait est que si vous vous souciez de la mémoire et que vous souhaitez que l'ensemble de l'objet soit supprimé de la mémoire, il est recommandé de le définir sur null avant de supprimer la clé:

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

L'autre point important ici est de faire attention à vos autres références au même objet. Par exemple, si vous créez une variable comme:

var regex = myJSONObject["regex"];

Ou ajoutez-le en tant que nouveau pointeur vers un autre objet comme:

var myOtherObject = {};
myOtherObject["regex"] = myJSONObject["regex"];

Ensuite, même si vous le supprimez de votre objet myJSONObject, cet objet spécifique ne sera pas supprimé de la mémoire, car la variable regex et myOtherObject["regex"] ont toujours leurs valeurs. Alors, comment pourrions-nous supprimer l'objet de la mémoire à coup sûr?

La réponse serait de supprimer toutes les références que vous avez dans votre code, pointé vers cet objet même et aussi de ne pas utiliser les instructions var pour créer de nouvelles références à cet objet . Ce dernier point concernant les instructions var, est l'un des problèmes les plus cruciaux auxquels nous sommes généralement confrontés, car l'utilisation des instructions var empêcherait la suppression de l'objet créé.

Ce qui signifie que dans ce cas, vous ne pourrez pas supprimer cet objet car vous avez créé la variable regex via une instruction var, et si vous le faites:

delete regex; //False

Le résultat serait false, ce qui signifie que votre instruction delete n'a pas été exécutée comme prévu. Mais si vous n'aviez pas créé cette variable auparavant et que vous n'aviez que myOtherObject["regex"] comme dernière référence existante, vous auriez pu le faire simplement en la supprimant comme:

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

En d'autres termes, un objet JavaScript est tué dès qu'il n'y a plus de référence dans votre code pointant vers cet objet.


Mettre à jour: Merci à @AgentME:

Définir une propriété sur null avant de la supprimer n'accomplit rien (sauf si l'objet a été scellé par Object.seal et que la suppression échoue. Ce n'est généralement pas le cas, sauf si vous essayez spécifiquement).

Pour obtenir plus d'informations sur Object.seal: Object.seal ()

48
Mehran Hatami 2 juin 2015 à 22:18

Mise à jour 2018-07-21: Depuis longtemps, je me sens gêné par cette réponse, donc je pense qu'il est temps de la retoucher un peu. Juste un petit commentaire, une clarification et un formatage pour aider à accélérer la lecture des parties inutilement longues et alambiquées de cette réponse.


LA VERSION COURTE

La réponse réelle à la question

Comme d'autres l'ont dit, vous pouvez utiliser delete.

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

Équivalent tableau

Ne pas delete à partir d'un tableau. Utilisez Array.prototype.splice à la place.

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

LA LONGUE VERSION

JavaScript est un langage OOP, donc tout est un objet, y compris les tableaux . Ainsi, j'estime nécessaire de signaler une mise en garde particulière.

Dans les tableaux, contrairement aux anciens objets simples, l'utilisation de delete laisse des déchets sous la forme de null, créant un "trou" dans le tableau.

var array = [1, 2, 3, 4];
delete array[2];
/* Expected result --> [1, 2, 4]
 * Actual result   --> [1, 2, null, 4]
 */

Comme vous pouvez le voir, delete ne fonctionne pas toujours comme on pourrait s'y attendre. La valeur est remplacée, mais la mémoire n'est pas réallouée. Autrement dit, array[4] n'est pas déplacé vers array[3]. Ce qui contraste avec Array.prototype.unshift, qui insère un élément au début du tableau et décale tout (array[0] devient array[1], etc.)

Honnêtement, mis à part la mise à null plutôt que undefined - ce qui est légitimement bizarre - ce comportement ne devrait pas être surprenant, car delete est unaire comme typeof, qui est dur dans le langage et n'est pas censé se soucier du type de l'objet sur lequel il est utilisé, alors que Array est une sous-classe de Object avec des méthodes spécialement conçues pour de travailler avec des tableaux. Il n'y a donc aucune bonne raison pour que delete ait un cas spécial préparé pour re-déplacer le tableau, car cela ralentirait les choses avec un travail inutile. Rétrospectivement, mes attentes n'étaient pas réalistes.

Bien sûr, cela m'a surpris. Parce que j'ai écrit ceci pour justifier ma croisade contre les "ordures nulles":

Ignorer les dangers et les problèmes inhérents à null et l'espace gaspillé, cela peut être problématique si le tableau doit être précis.

Ce qui est une terrible justification pour se débarrasser des null s - null n'est dangereux que s'il est mal utilisé, et cela n'a rien à voir avec la "précision". La vraie raison pour laquelle vous ne devriez pas delete à partir d'un tableau est que laisser des structures de données remplies de déchets et désordonnées est bâclé et sujet aux bogues.

Ce qui suit est un scénario artificiel qui devient assez long, vous pouvez donc passer à la section La solution , si vous le souhaitez. La seule raison pour laquelle je quitte cette section, c'est que je pense que certaines personnes pensent probablement que c'est drôle, et je ne veux pas être "ce gars" qui publie une réponse "drôle" puis en supprime tous les "drôles" plus tard. .

... C'est stupide, je sais.

Le scénario PDP-11 artificiel et de longue haleine

Par exemple, supposons que vous créez une application Web qui utilise la sérialisation JSON pour stocker un tableau utilisé pour les «tabulations» dans une chaîne (dans ce cas, localStorage). Supposons également que le code utilise les indices numériques des membres du tableau pour les "titrer" lors du dessin à l'écran. Pourquoi faites-vous cela plutôt que de simplement stocker le "titre" également? Parce que ... raisons .

D'accord, disons simplement que vous essayez d'économiser de la mémoire à la demande de cet un utilisateur qui exécute un mini-ordinateur PDP-11 des années 1960 sous UNIX et a écrit son propre Elinks, conforme à JavaScript , navigateur convivial pour les imprimantes en ligne car X11 est hors de question .

Mis à part le scénario de bord de plus en plus stupide, l'utilisation de delete sur ledit tableau résultera en null polluant le tableau, et provoquant probablement des bogues dans l'application plus tard. Et si vous vérifiez null, il sautera directement les nombres, ce qui entraînera le rendu des onglets comme [1] [2] [4] [5] ....

if (array[index] == null)
    continue;
else
    title = (index + 1).toString();
/* 0 -> "1"
 * 1 -> "2"
 * 2 -> (nothing)
 * 3 -> "4"
 */

Ouais, ce n'est certainement pas ce que tu voulais.

Maintenant, vous pourriez conserver un deuxième itérateur, comme j, pour incrémenter uniquement lorsque des valeurs valides sont lues dans le tableau. Mais cela ne résoudrait pas exactement le problème de null, et vous devez toujours plaire à cet utilisateur de PDP-11 troll . Hélas, son ordinateur n'a pas assez de mémoire pour contenir ce dernier entier (ne lui demandez pas comment il parvient à gérer un tableau à largeur variable ...) .

Alors, il vous envoie un email en colère:

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

À présent, vous êtes à bout de souffle. Ce gars s'est plaint sans arrêt de votre application, et vous voulez lui dire de se taire et d'aller chercher un meilleur ordinateur.

La solution: Array.prototype.splice

Heureusement, les tableaux do ont une méthode spécialisée pour supprimer les index et réallouer la mémoire: Array.prototype.splice(). Vous pouvez écrire quelque chose comme ceci:

Array.prototype.remove = function(index){
  this.splice(index,1);
}
...
array = [1, 2, 3, 4];
array.remove(2);
// Result -> [1, 2, 4]

Et juste comme ça, vous avez plu à M. PDP-11. Hourra! (je lui dirais quand même, mais ...)

Array.prototype.splice vs Array.prototype.slice

Je pense qu'il est important de souligner la différence entre ces deux fonctions portant le même nom, car elles sont toutes deux très utiles.

Array.prototype.splice (début, n)

.splice() mute le tableau et renvoie les indices supprimés. Le tableau est découpé à partir de l'index, les éléments start et n sont découpés. Si n n'est pas spécifié, l'ensemble du tableau après start est découpé (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 (début, fin)

.slice() est non destructif et renvoie un nouveau tableau contenant les indices indiqués de start à end. Si end n'est pas spécifié, le comportement est le même que .splice() (end = array.length). Le comportement est un peu délicat car, pour une raison quelconque, end indexe de 1 au lieu de 0. Je ne sais pas pourquoi il fait cela, mais c'est comme ça. De plus, si end <= start, le résultat est un tableau vide.

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]

Ce n'est pas vraiment ce qui se passe, mais c'est plus facile de penser de cette façon. Selon MDN, voici ce qui se passe réellement:

// 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

L'index spécifié par end est simplement exclu de la tranche. Les indices entre parenthèses indiquent ce qui est coupé. Quoi qu'il en soit, le comportement n'est pas intuitif et il est susceptible de provoquer sa juste part d'erreurs off-by-one, donc vous pourriez trouver utile de créer une fonction wrapper pour émuler plus étroitement le comportement 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);
}

Notez que la fonction wrapper est conçue pour être très stricte sur les types et retournera null si quelque chose est désactivé. Cela inclut de mettre une chaîne comme "3". Il appartient au programmeur de faire preuve de diligence au sujet de ses types. Il s'agit d'encourager de bonnes pratiques de programmation.

Mise à jour concernant is_array()

Cela concerne cet extrait (désormais supprimé):

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

Ainsi, il s'avère qu'il existe en fait un moyen intégré de dire si un tableau est vraiment un tableau, et c'est Array.isArray(), introduit dans ECMAScript 5 (décembre 2009). J'ai trouvé cela en regardant pour voir s'il y avait une question demandant de dire des tableaux à partir d'objets, pour voir s'il y avait une meilleure solution que la mienne, ou pour ajouter la mienne s'il n'y en avait pas. Donc, si vous utilisez une version de JavaScript antérieure à ECMA 5, il y a votre polyfill. Cependant, je déconseille fortement d'utiliser ma fonction is_array(), car continuer à prendre en charge les anciennes versions de JavaScript signifie continuer à prendre en charge les anciens navigateurs qui les implémentent, ce qui signifie encourager l'utilisation de logiciels non sécurisés et mettre les utilisateurs à risque de logiciels malveillants. Veuillez donc utiliser Array.isArray(). Utilisez let et const. Utilisez les nouvelles fonctionnalités qui s'ajoutent à la langue. Ne pas utiliser des préfixes de fournisseurs. Supprimer cette merde de polyfill IE de votre site Web. Supprimez également cette merde XHTML <!CDATA[[... - nous sommes passés à HTML5 en 2014. Plus tôt tout le monde retire la prise en charge de ces anciens navigateurs / ésotériques, plus tôt les fournisseurs de navigateurs suivront réellement la norme Web et adopteront la nouvelle technologie, et le plus tôt nous pourrons passer à un site Web plus sécurisé.

209
Braden Best 27 avril 2019 à 03:47
208105