Disons que je crée un objet comme suit :
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
Quelle est la meilleure façon de supprimer la propriété regex
pour obtenir le nouvel myObject
suivant ?
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI"
};
Comme ça :
delete myObject.regex;
// or,
delete myObject['regex'];
// or,
var prop = "regex";
delete myObject[prop];
Démonstration
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
delete myObject.regex;
console.log(myObject);
Pour tous ceux qui souhaitent en savoir plus, l'utilisateur de Stack Overflow [kangax][1] a rédigé un billet incroyablement détaillé sur l'instruction delete
sur son blog, [Understanding delete][2]. Nous vous le recommandons vivement.
[1] : https://stackoverflow.com/users/130652/kangax [2] : http://perfectionkills.com/understanding-delete/
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.
Mise à jour 2018-07-21: Pendant longtemps, je me suis senti gêné par cette réponse, alors je pense qu'il est temps que je la retouche 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.
obj // {"foo": "bar"}
delete obj["foo"]
obj // {}
obj["foo"] // undefined
N'utilisez pas delete
dans un tableau. Utilisez plutôt Array.prototype.splice
.
arr // [1,2,3,4,5]
arr.splice(3,1); // 4
arr // [1,2,3,5]
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 écrasée, mais la mémoire n'est pas réallouée. En d'autres termes, array[4]
n'est pas relocalisé dans array[3]
. Contrairement à Array.prototype.unshift
, qui insère un élément au début du tableau et décale tout vers le haut (array[0]
devient array[1]
, etc.).
Honnêtement, à part le fait de mettre à null
plutôt qu'à undefined
- ce qui est légitimement bizarre - ce comportement ne devrait pas être surprenant, puisque delete
est un opérateur unaire, comme typeof
, qui est ancré dans le langage et qui n'est pas censé se soucier du type d'objet sur lequel il est utilisé, alors que Array
est une sous-classe de Object
avec des méthodes spécifiquement conçues pour travailler avec des tableaux. Il n'y a donc aucune raison pour que delete
ait un cas spécial pour déplacer le tableau, car cela ne ferait que ralentir les choses avec un travail inutile. Rétrospectivement, mes attentes étaient irréalistes.
Bien sûr, cela m'a surpris. Parce que j'ai écrit ceci pour justifier ma croisade contre les "null garbage" :
En ignorant 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 justification terrible pour se débarrasser desnull
s -null
n'est dangereux que s'il est utilisé incorrectement, et cela n'a rien à voir avec la "précision". La vraie raison pour laquelle vous ne devriez passupprimer
un tableau est que laisser des structures de données pleines de déchets et désordonnées est négligé et sujet à des bogues. Ce qui suit est un scénario inventé qui devient assez long, donc vous pouvez sauter à la section, La Solution, si vous voulez. La seule raison pour laquelle je laisse cette section est que je pense que certaines personnes la trouvent probablement amusante, et je ne veux pas être "ce type" qui poste une réponse "amusante" puis supprime tout ce qui est "amusant" par la suite. ...C'est stupide, je sais.Le scénario inventé et interminable du PDP-11
Par exemple, disons que vous créez une application web qui utilise la sérialisation JSON pour stocker un tableau utilisé pour les 'tabs' dans une chaîne (dans ce cas,
localStorage
). Disons également que le code utilise les indices numériques des membres du tableau pour les "titrer" lors de l'affichage à l'écran. Pourquoi faire cela plutôt que de simplement stocker le "titre" également ? Parce que... raisons. Disons que vous essayez d'économiser de la mémoire à la demande de cet un seul utilisateur qui utilise un mini-ordinateur PDP-11 des années 1960 fonctionnant sous UNIX et qui a écrit son propre navigateur basé sur Elinks, compatible JavaScript et adapté à l'impression en ligne parce que X11 est hors de question. En dehors de ce scénario de plus en plus stupide, l'utilisation dedelete
sur ledit tableau aura pour conséquence de polluer le tableau avecnull
, ce qui causera probablement des bugs dans l'application par la suite. Et si vous vérifiez pournull
, il sauterait directement les nombres résultant en un rendu des onglets comme[1] [2] [4] [5] ...
. if (array[index] == null) continuez ; else title = (index + 1).toString() ; /* 0 -> "1"
- 1 -> "2"
- 2 -> (rien)
- 3 -> "4" / Oui, ce n'est certainement pas ce que vous vouliez. Maintenant, vous pourriez garder un second itérateur, comme
j
, pour ne l'incrémenter que lorsque des valeurs valides sont lues dans le tableau. Mais cela ne résoudrait pas exactement le problème dunull
, et vous devez toujours satisfaire cettrollutilisateur de PDP-11. Hélas, son ordinateur n'a tout simplement pas* assez de mémoire pour contenir ce dernier entier (ne demandez pas comment il arrive à gérer un tableau de largeur variable...). Alors, il vous envoie un e-mail de colère : Hey, votre webapp a cassé mon navigateur ! J'ai vérifié ma base de données localStorage après que votre code stupide ait provoqué une défaillance de mon navigateur, et voici ce que j'ai trouvé :"tabs :[ 'Hello World', 'foo bar baz', null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, ... ]" Après avoir effacé mes précieuses données, il s'est à nouveau planté, et j'ai fait un backtrace, et qu'est-ce que j'ai trouvé ? QU'EST-CE QUE JE TROUVE ? VOUS UTILISEZ TROP DE VARIABLES ! var i = index ; var j = 1 ; Grr, je suis en colère maintenant. -Troll Davidson Vous êtes à bout de nerfs. Ce type n'a pas arrêté de se plaindre 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 ont une méthode spécialisée pour effacer les indices et réallouer la mémoire :
Array.prototype.splice()
. Vous pourriez é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 fait plaisir à Mr. PDP-11. Hourra ! (Je le gronderais quand même...)
Il me semble important de souligner la différence entre ces deux fonctions au nom similaire, car elles sont toutes deux très utiles.
.splice()
mute le tableau, et retourne les indices retirés. Le tableau est découpé à partir de l'indice start
, et n
éléments sont découpés. Si n n'est pas spécifié, le tableau entier 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]
.slice()
est non-destructif et retourne 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 celui de .splice()
(end = array.length
). Le comportement est un peu délicat car, pour une raison quelconque, end
indexe à partir de 1 au lieu de 0. Je ne sais pas pourquoi il fait ça, mais c'est comme ça. Aussi, 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]
En fait, ce n'est pas ce qui se passe, mais c'est plus facile à 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 découpé en tranches. Quoi qu'il en soit, le comportement n'est pas intuitif et il est voué à causer sa part d'erreurs de type "off-by-one", donc vous pourriez trouver utile de faire une fonction d'enveloppe 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 quoi que ce soit est incorrect. Cela inclut la mise en place d'une chaîne comme "3". C'est au programmeur de faire attention à ses types. Ceci est pour encourager les bonnes pratiques de programmation.
is_array()
Ceci est en rapport avec ce snippet (maintenant supprimé) :
function is_array(array){
return array !== null
&& typeof array === "object"
&& typeof array.length !== "undefined"
&& array.__proto__ === Array.prototype;
}
Il s'avère qu'il existe en fait un moyen intégré pour dire si un tableau est vraiment un tableau, et c'est Array.isArray()
, introduit dans ECMAScript 5 (décembre 2009). J'ai trouvé ceci en cherchant à voir s'il y avait une question sur la façon de distinguer les tableaux des 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, vous avez votre polyfill. Cependant, je vous déconseille fortement d'utiliser ma fonction is_array()
, car continuer à supporter les anciennes versions de JavaScript signifie continuer à supporter les anciens navigateurs qui les implémentent, ce qui signifie encourager l'utilisation de logiciels non sécurisés et mettre les utilisateurs en danger pour les malwares. Alors s'il vous plaît, utilisez Array.isArray()
. Utilisez let
et const
. Utilisez les nouvelles fonctionnalités qui sont ajoutées au langage. N'utilisez pas les préfixes des fournisseurs. Supprimez cette merde de polyfill IE de votre site Web. Supprimez aussi cette merde XHTML <!CDATA[[...
-- nous sommes passés à HTML5 en 2014. Plus vite tout le monde retirera le support de ces navigateurs anciens/ésotériques, plus vite les vendeurs de navigateurs suivront réellement le standard web et adopteront la nouvelle technologie, et plus vite nous pourrons passer à un web plus sécurisé.