Povedzme, že vytvorím objekt takto:
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
Aký je najlepší spôsob, ako odstrániť vlastnosť regex
, aby vznikol nový myObject
takto?
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI"
};
Takto:
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);
Pre všetkých, ktorí majú záujem prečítať si o tom viac, používateľ Stack Overflow kangax napísal neuveriteľne podrobný príspevok o príkaze delete
na svojom blogu Understanding delete. Veľmi ho odporúčame.
var myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
delete myObject.regex;
console.log ( myObject.regex); // logs: undefined
Toto funguje vo Firefoxe a Internet Exploreri a myslím, že to funguje aj vo všetkých ostatných.
Aktualizácia 2018-07-21: Dlho som sa za túto odpoveď hanbil, takže si myslím, že je čas, aby som ju trochu vylepšil. Len malý komentár, upresnenie a formátovanie, ktoré pomôže urýchliť čítanie zbytočne dlhých a spletitých častí tejto odpovede.
obj // {"foo": "bar"}
delete obj["foo"]
obj // {}
obj["foo"] // undefined
Neodstraňujte delete
z poľa. Namiesto toho použite 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]
*/
Ako vidíte, delete
nefunguje vždy tak, ako by sme očakávali. Hodnota je prepísaná, ale pamäť nie je znovu pridelená. To znamená, že array[4]
nie je premiestnený do array[3]
. To je v protiklade s funkciou Array.prototype.unshift
, ktorá vloží prvok na začiatok poľa a všetko posunie nahor (z array[0]
sa stane array[1]
atď.)
Úprimne povedané, okrem nastavenia na null
namiesto undefined
- čo je oprávnene divné - by toto správanie nemalo byť prekvapujúce, pretože delete
je unárny operátor, podobne ako typeof
, ktorý je pevne zakotvený v jazyku a nemá sa starať o typ objektu, na ktorom sa používa, zatiaľ čo Array
je podtrieda Object
s metódami *konkrétne určenými na prácu s poliami. Takže nie je žiadny dobrý dôvod, aby delete
malo špeciálny prípad pre zmenu posunu poľa, pretože by to len zbytočne spomaľovalo prácu. Spätne vidím, že moje očakávania boli nerealistické.
Samozrejme, prekvapilo ma to. Pretože som to napísal, aby som ospravedlnil svoje krížové ťaženie proti "null garbage":
Ignorujúc nebezpečenstvá a problémy spojené s
null
a plytvaním miestom, môže to byť problematické, ak pole potrebuje byť presné. Čo je strašné zdôvodnenie na to, aby sme sa zbavilinull
--null
je nebezpečné len vtedy, ak sa používa nesprávne, a nemá nič spoločné s "presnosťou". Skutočným dôvodom, prečo by ste nemalizmazať
z poľa, je to, že ponechávať po sebe odpadky a chaotické dátové štruktúry je nedbalé a náchylné na chyby. Nasleduje vymyslený scenár, ktorý je dosť rozvláčny, takže ak chcete, môžete preskočiť na časť Riešenie. Jediný dôvod, prečo som túto časť ponechal, je ten, že si myslím, že niektorí ľudia si pravdepodobne myslia, že je to smiešne, a ja nechcem byť "ten chlapík", ktorý uverejní "smiešnu" odpoveď a neskôr z nej vymaže všetko "smiešne". ...Je to hlúpe, ja viem.Vymyslený a zdĺhavý scenár PDP-11
Napríklad povedzme, že vytvárate webovú aplikáciu, ktorá používa JSON-serializáciu na uloženie poľa používaného pre 'záložky' v reťazci (v tomto prípade
localStorage
). Povedzme tiež, že kód používa číselné indexy členov poľa'na ich "title" pri vykresľovaní na obrazovku. Prečo to robíte namiesto toho, aby ste uložili aj "title"? Pretože... dôvody. Dobre, povedzme, že sa snažíte ušetriť pamäť na žiadosť tohto jediného používateľa, ktorý používa minipočítač PDP-11 zo 60. rokov so systémom UNIX a napísal si vlastný prehliadač založený na Elinks, kompatibilný s JavaScriptom, vhodný pre riadkovú tlačiareň, pretože X11 je neprimeraný. Odhliadnuc od čoraz hlúpejšieho okrajového scenára, použitiedelete
na uvedenom poli bude mať za následok znečistenie poľanull
a pravdepodobne spôsobí neskoršie chyby v aplikácii. A ak by ste kontrolovalinull
, rovno by to vynechalo čísla, čo by viedlo k tomu, že by sa karty vykresľovali ako[1] [2] [4] [5] ...
. if (array[index] == null) pokračovať; inak title = (index + 1).toString(); /* 0 -> "1"
- 1 -> "2"
- 2 -> (nič)
- 3 -> "4" / Áno, to určite nie je to, čo ste chceli. Teraz by ste mohli mať druhý iterátor, napríklad
j
, ktorý by inkrementoval len vtedy, keď sa z poľa načítajú platné hodnoty. Ale to by'presne nevyriešilo problémnull
a stále by ste museli potešiť tohotrollapoužívateľa PDP-11. Žiaľ, jeho počítač jednoducho nemá dostatok pamäte na to, aby sa do nej zmestilo posledné celé číslo (nepýtajte sa, ako zvláda spracovať pole s premenlivou šírkou...). Takže vám v hneve pošle e-mail: Hej, tvoja webová aplikácia mi rozbila prehliadač! Skontroloval som svoju databázu localStorage po tom, čo tvoj hlúpy kód spôsobil segfault môjho prehliadača, a toto som našiel:"tabs:['Hello World', 'foo bar baz', null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, ... ]" Po vymazaní mojich drahocenných dát, to segfaulted znova, a ja som backtrace, a čo som našiel? ČO SOM NAŠIEL? POUŽÍVATE PRÍLIŠ VEĽA PREMENNÝCH! var i = index; var j = 1; Grr, teraz som nahnevaný. -Troll Davidson Približne teraz si v koncoch s rozumom. Tento chlapík sa nepretržite sťažuje na vašu aplikáciu a vy mu chcete povedať, aby držal hubu a išiel si kúpiť lepší počítač.
Riešenie:
Array.prototype.splice
Našťastie polia majú špecializovanú metódu na mazanie indexov a realokáciu pamäte:
Array.prototype.splice()
. Mohli by ste napísať niečo takéto:
Array.prototype.remove = function(index){
this.splice(index,1);
}
...
array = [1, 2, 3, 4];
array.remove(2);
// Result -> [1, 2, 4]
A práve tak ste potešili pána PDP-11. Hurá! (Aj tak by som mu vynadal...)
Považujem'za dôležité poukázať na rozdiel medzi týmito dvoma podobne pomenovanými funkciami, pretože obe sú veľmi užitočné.
.splice()
zmutuje pole a vráti odstránené indexy. Pole sa rozreže počnúc indexom start
a vyreže sa n
prvkov. Ak n nie je zadané, vyreže sa celé pole po 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]
.slice()
je nedeštruktívne a vracia nové pole obsahujúce uvedené indexy od start
do end
. Ak end
nie je zadaný, správanie je rovnaké ako pri .splice()
(end = array.length
). Správanie je trochu komplikované, pretože z nejakého dôvodu sa end
indexuje od 1 namiesto 0. Neviem, prečo to robí, ale je to tak. Taktiež, ak end <= start
, výsledkom je prázdne pole.
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]
V skutočnosti to tak nie je, ale je jednoduchšie si to tak predstaviť. Podľa MDN sa v skutočnosti deje toto:
// 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
Index zadaný pomocou end
je jednoducho vylúčený z reze. Indexy v zátvorkách označujú, čo sa bude krájať. Tak či onak, toto správanie nie je intuitívne a určite'spôsobí dostatočný podiel chýb mimo jednotiek, takže by mohlo byť užitočné vytvoriť obalovú funkciu, ktorá by lepšie napodobňovala správanie funkcie .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);
}
Všimnite si, že obalová funkcia je navrhnutá tak, aby bola veľmi prísna na typy a vráti null
, ak je niečo mimo. To zahŕňa aj vloženie reťazca ako "3"
. Je ponechané na programátorovi, aby bol dôsledný v otázke typov. Týmto sa má podporiť správna programátorská prax.
is_array()
Toto sa týka tohto (teraz odstráneného) úryvku:
function is_array(array){
return array !== null
&& typeof array === "object"
&& typeof array.length !== "undefined"
&& array.__proto__ === Array.prototype;
}
Ako sa ukázalo, v skutočnosti existuje zabudovaný spôsob, ako zistiť, či je pole skutočne pole, a to Array.isArray()
, zavedený v ECMAScripte 5 (december 2009). Našiel som to, keď som hľadal, či tu nie je otázka, ktorá sa pýta na rozoznávanie polí od objektov, aby som zistil, či existuje lepšie riešenie ako moje, alebo aby som pridal svoje, ak žiadne neexistuje. Takže ak používate verziu JavaScriptu, ktorá je staršia ako ECMA 5, je tu vaša polyfill. Dôrazne však neodporúčam používať moju funkciu is_array()
, pretože pokračovať v podpore starých verzií JavaScriptu znamená pokračovať v podpore starých prehliadačov, ktoré ich implementujú, čo znamená podporovať používanie nezabezpečeného softvéru a vystavovať používateľov riziku škodlivého softvéru. Preto prosím používajte funkciu Array.isArray()
. Používajte let
a const
. Používajte nové funkcie, ktoré sa pridávajú do jazyka. Nepoužívajte prefixy výrobcov. Odstráňte zo svojej webovej stránky tie polyfillové sračky IE. Odstráňte aj to svinstvo XHTML <!CDATA[[...
- v roku 2014 sme prešli na HTML5. Čím skôr všetci zrušia podporu týchto starých/esoterických prehliadačov, tým skôr budú výrobcovia prehliadačov skutočne dodržiavať webový štandard a prijmú novú technológiu, a tým skôr budeme môcť prejsť na bezpečnejší web.