Diciamo che creo un oggetto come segue:
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
Qual è il modo migliore per rimuovere la proprietà regex
per finire con il nuovo myObject
come segue?
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI"
};
Come questo:
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);
Per chiunque sia interessato a leggerne di più, l'utente di Stack Overflow kangax ha scritto un post incredibilmente approfondito sull'istruzione delete
sul suo blog, Understanding delete. È altamente raccomandato.
var myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
delete myObject.regex;
console.log ( myObject.regex); // logs: undefined
Questo funziona in Firefox e Internet Explorer, e penso che funzioni in tutti gli altri.
Aggiornamento 2018-07-21: Per molto tempo, mi sono sentito in imbarazzo per questa risposta, quindi penso che sia il momento di ritoccarla un po'. Solo un piccolo commento, chiarimento e formattazione per aiutare ad accelerare la lettura delle parti inutilmente lunghe e contorte di questa risposta. Traduzione: #argomenta, #salvezza, #salvezza, #salvezza, #salvezza;
Come altri hanno detto, puoi usare delete
.
obj // {"foo": "bar"}
delete obj["foo"]
obj // {}
obj["foo"] // undefined
Non cancellare
da un array. Usa invece Array.prototype.splice
.
arr // [1,2,3,4,5]
arr.splice(3,1); // 4
arr // [1,2,3,5]
hr>
JavaScript è un linguaggio OOP, quindi tutto è un oggetto, inclusi gli array. Quindi, sento la necessità di sottolineare un particolare avvertimento.
Negli array, a differenza dei semplici vecchi oggetti, usare delete
lascia dietro di sé spazzatura sotto forma di null
, creando un "buco" nell'array.
var array = [1, 2, 3, 4];
delete array[2];
/* Expected result --> [1, 2, 4]
* Actual result --> [1, 2, null, 4]
*/
Come potete vedere, delete
non funziona sempre come ci si potrebbe aspettare. Il valore viene sovrascritto, ma la memoria non viene riallocata. Cioè, array[4]
non viene ricollocato in array[3]
. Il che è in contrasto con Array.prototype.unshift
, che inserisce un elemento all'inizio dell'array e sposta tutto in alto (array[0]
diventa array[1]
, ecc.)
Onestamente, a parte l'impostazione su null
piuttosto che su undefined
- che è legittimamente strano - questo comportamento non dovrebbe essere sorprendente, dato che delete
è un operatore unario, come typeof
, che è stato inserito nel linguaggio e non si suppone si preoccupi del tipo di oggetto su cui viene usato, mentre Array
è una sottoclasse di Object
con metodi specificamente progettati per lavorare con gli array. Quindi non c'è una buona ragione per cui delete
abbia un caso speciale per spostare l'array, in quanto ciò rallenterebbe solo le cose con un lavoro inutile. In retrospettiva, le mie aspettative non erano realistiche.
Naturalmente, mi ha sorpreso. Perché ho scritto questo per giustificare la mia crociata contro "null garbage":
Ignorando i pericoli e i problemi inerenti a null
, e lo spazio sprecato, questo può essere problematico se l'array deve essere preciso.
Il che è una terribile giustificazione per sbarazzarsi dei null
--null
è pericoloso solo se usato impropriamente, e non ha niente a che fare con la "precisione". La vera ragione per cui non si dovrebbe "cancellare" da un array è che lasciare in giro strutture di dati riempite di spazzatura e disordinate è sciatto e soggetto a bug.
Quello che segue è uno scenario artificioso che diventa piuttosto prolisso, quindi potete saltare alla sezione, La soluzione, se volete. L'unica ragione per cui lascio questa sezione è che penso che alcune persone probabilmente pensano che sia divertente, e non voglio essere il tipo che pubblica una risposta "divertente" e poi cancella tutto il "divertente" da essa in seguito.
...È stupido, lo so.
Per esempio, diciamo che state creando una webapp che usa la serializzazione JSON per memorizzare un array usato per 'tabs' in una stringa (in questo caso, localStorage
). Diciamo anche che il codice usa gli indici numerici dei membri dell'array per "intitolarli" quando li disegna sullo schermo. Perché fai questo invece di memorizzare anche il "titolo"? Perché... ragioni.
Ok, diciamo solo che stai cercando di risparmiare memoria su richiesta di questo unico utente che ha un minicomputer PDP-11 del 1960 con UNIX e ha scritto il suo browser basato su Elinks, conforme a JavaScript e adatto alla stampa in linea, perché X11 è fuori questione. A parte il sempre più stupido scenario marginale, l'uso di
delete
su tale array avrà come risultato chenull
inquinerà l'array, e probabilmente causerà bug nell'applicazione in seguito. E se si controlla la presenza dinull
, salterebbe direttamente i numeri con il risultato che le schede sarebbero rese come[1] [2] [4] [5] ...
. if (array[index] == null) continua; altrimenti title = (index + 1).toString(); /* 0 -> "1"
- 1 -> "2"
- 2 -> (niente)
- 3 -> "4" / Gia', non e' sicuramente quello che volevi. Ora, si potrebbe tenere un secondo iteratore, come
j
, per incrementare solo quando vengono letti valori validi dall'array. Ma questo non risolverebbe esattamente il problema deinull
, e devi ancora accontentare queltrollutente PDP-11. Ahimè, il suo computer semplicemente non'ha abbastanza memoria per contenere quell'ultimo intero (non chiedete come riesce a gestire un array di larghezza variabile...). Quindi, ti manda un'email con rabbia: Ehi, la tua webapp ha rotto il mio browser! Ho controllato il mio database localStorage dopo che il tuo stupido codice ha reso il mio browser segfault, e questo è quello che ho trovato: "tabs:['Hello World', 'foo bar baz', null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, ... ]" Dopo aver cancellato i miei preziosi dati, ha avuto un nuovo segfault, e ho fatto un backtrace, e cosa trovo? COSA TROVO!? USI TROPPE VARIABILI!var i = indice; var j = 1; Grr, ora sono arrabbiato. -Troll Davidson A questo punto, sei allo stremo delle forze. Questo tizio si sta lamentando senza sosta della tua app, e tu vuoi dirgli di stare zitto e andare a prendere un computer migliore.
La soluzione:
Array.prototype.splice
.Fortunatamente, gli array hanno un metodo specializzato per cancellare gli indici e riallocare la memoria:
Array.prototype.splice()
. Si potrebbe scrivere qualcosa del genere:
Array.prototype.remove = function(index){
this.splice(index,1);
}
...
array = [1, 2, 3, 4];
array.remove(2);
// Result -> [1, 2, 4]
E proprio così, avete accontentato il signor PDP-11. Urrà! (Io lo manderei ancora a quel paese, però...);
Mi sembra importante sottolineare la differenza tra queste due funzioni dal nome simile, dato che sono entrambe molto utili.
.splice()
muta l'array e restituisce gli indici rimossi. L'array viene tagliato a partire dall'indice start
, e n
elementi vengono tagliati fuori. Se n non è specificato, l'intero array dopo start
viene tagliato fuori (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()
non è distruttivo e restituisce un nuovo array contenente gli indici indicati da start
a end
. Se end
è lasciato non specificato, il comportamento è lo stesso di .splice()
(end = array.length
). Il comportamento è un po' complicato poiché, per qualche ragione, end
indicizza da 1 invece che da 0. Non so perché lo faccia, ma è così. Inoltre, se end <= start
, il risultato è un array vuoto.
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]
Questo in realtà non è quello che succede, ma è più facile da pensare in questo modo. Secondo MDN, ecco cosa sta realmente accadendo:
// 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'indice specificato da end
viene semplicemente escluso dalla fetta. Gli indici tra parentesi indicano cosa viene affettato. In ogni caso, il comportamento non è intuitivo ed è destinato a causare la sua giusta quota di errori off-by-one, quindi potreste trovare utile fare una funzione wrapper per emulare più da vicino il comportamento di .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);
}
Notate che la funzione wrapper è progettata per essere molto rigorosa sui tipi, e restituirà null
se qualcosa non va. Questo include mettere una stringa come "3"
. È lasciato al programmatore il compito di essere diligente riguardo ai suoi tipi. Questo è per incoraggiare una buona pratica di programmazione.
is_array()
Questo riguarda questo snippet (ora rimosso):
function is_array(array){
return array !== null
&& typeof array === "object"
&& typeof array.length !== "undefined"
&& array.__proto__ === Array.prototype;
}
Quindi, come si è scoperto, c'è effettivamente un modo integrato per dire se un array è veramente un array, ed è Array.isArray()
, introdotto in ECMAScript 5 (dicembre 2009). Ho trovato questo mentre cercavo di vedere se c'era una domanda che chiedeva di distinguere gli array dagli oggetti, per vedere se c'era una soluzione migliore della mia, o per aggiungere la mia se non ce n'erano. Quindi, se state usando una versione di JavaScript che è precedente a ECMA 5, ecco il vostro polyfill. Tuttavia, sconsiglio vivamente di usare la mia funzione is_array()
, poiché continuare a supportare vecchie versioni di JavaScript significa continuare a supportare i vecchi browser che le implementano, il che significa incoraggiare l'uso di software insicuro e mettere gli utenti a rischio di malware. Quindi, per favore, usate Array.isArray()
. Usate let
e const
. Usate le nuove caratteristiche che vengono aggiunte al linguaggio. Non'usare i prefissi dei venditori. Eliminate* quella merda di polyfill di IE dal vostro sito web. Cancella anche quella merda XHTML <!CDATA[[...
- siamo passati a HTML5 nel 2014. Prima tutti ritirano il supporto per quei browser vecchi/esoterici, prima i produttori di browser seguiranno effettivamente lo standard web e abbracceranno la nuova tecnologia, e prima potremo passare a un web più sicuro.