verwijder a.x vs a.x = undefined

Is er een wezenlijk verschil in het doen van een van beide?

delete a.x;

vs

a.x = undefined;

waar

a = {
    x: 'boo'
};

kan men zeggen dat ze gelijkwaardig zijn?

(Ik houd geen rekening met dingen als “V8 gebruikt liever niet deletebetter”)


Antwoord 1, autoriteit 100%

Ze zijn niet gelijkwaardig. Het belangrijkste verschil is die instelling

a.x = undefined

betekent dat a.hasOwnProperty("x")nog steeds true retourneert, en daarom zal het nog steeds verschijnen in een for in-lus en in Object.keys()

delete a.x

betekent dat a.hasOwnProperty("x")false retourneert

De manier waarop ze hetzelfde zijn, is dat je niet kunt zien of een eigenschap bestaat door te testen

if (a.x === undefined)

Wat u niet moet doen als u probeert te bepalen of een eigenschap bestaat, u moet altijd

gebruiken

// If you want inherited properties
if ('x' in a)
// If you don't want inherited properties
if (a.hasOwnProperty('x'))

De prototypeketen volgen(vermeld door zzzzBov) Door deleteaan te roepen, kan het omhoog gaan in de prototypeketen, terwijl het instellen van de waarde op undefined niet zal zoeken naar de eigenschap in de geketende prototypes http://jsfiddle.net/NEEw4/1/

var obj = {x: "fromPrototype"};
var extended = Object.create(obj);
extended.x = "overriding";
console.log(extended.x); // overriding
extended.x  = undefined;
console.log(extended.x); // undefined
delete extended.x;
console.log(extended.x); // fromPrototype

Overgenomen eigenschappen verwijderenAls de eigenschap die u probeert te verwijderen is overgenomen, heeft deletehier geen invloed op. Dat wil zeggen, deleteverwijdert alleen eigenschappen van het object zelf, geen overgeërfde eigenschappen.

var obj = {x: "fromPrototype"};
var extended = Object.create(obj);
delete extended.x;
console.log(extended.x); // Still fromPrototype

Daarom, als u ervoor moet zorgen dat de waarde van een object ongedefinieerd is, zal deleteniet werken wanneer de eigenschap wordt overgenomen, u moet het instellen (overschrijven) op undefinedin dat geval. Tenzij de plaats die ernaar zoekt hasOwnPropertyzal gebruiken, maar het is waarschijnlijk niet veilig om aan te nemen dat overal waar wordt gecontroleerd het hasOwnProperty

zal gebruiken


Antwoord 2, autoriteit 17%

Om de vraag te parafraseren:

Zijn delete a.xen a.x = undefinedequivalent?

Nee.

De eerste verwijdert de sleutel uit de variabele, de latere stelt de sleutel in met een waarde van undefined. Dit maakt een verschil bij het herhalen van eigenschappen van objecten en wanneer hasOwnPropertywordt gebruikt.

a = {
    x: true
};
a.x = undefined;
a.hasOwnProperty('x'); //true
delete a.x;
a.hasOwnProperty('x'); //false

Bovendien zal dit een aanzienlijk verschil maken als het om de prototypeketen gaat.

function Foo() {
    this.x = 'instance';
}
Foo.prototype = {
    x: 'prototype'
};
a = new Foo();
console.log(a.x); //'instance'
a.x = undefined;
console.log(a.x); //undefined
delete a.x;
console.log(a.x); //'prototype'

Antwoord 3, autoriteit 2%

Als a.xeen setter-functie is, roept a.x = undefinedde functie aan, terwijl delete a.xde functie niet aanroept.

>


Antwoord 4

Ja, er is een verschil.
Als je delete a.xgebruikt, is de x niet langer een eigenschap van a, maar als je a.x=undefinedgebruikt, is het een eigenschap maar de waarde ervan is niet gedefinieerd.


Antwoord 5

De namen zijn een beetje verwarrend. a.x = undefinedzet de eigenschap gewoon op undefined, maar de eigenschap is er nog steeds:

> var a = {x: 3};
> a.x = undefined;
> a.constructor.keys(a)
["x"]

deleteverwijdert het daadwerkelijk:

> var a = {x: 3};
> delete a.x;
> a.constructor.keys(a)
[]

Antwoord 6

Deze REPL van node zou het verschil moeten illustreren.

> a={ x: 'foo' };
{ x: 'foo' }
> for (var i in a) { console.log(i); };
x
undefined
> a.x=undefined;
undefined
> for (var i in a) { console.log(i); };
x
undefined
> delete a.x;
true
> for (var i in a) { console.log(i); };
undefined

Antwoord 7

Ik weet zeker dat je het verschil kunt zien tussen var o1 = {p:undefined};en var o2 = {};.

In beide gevallen zal o.pundefinedzijn, maar in het eerste geval is dat omdat dat de waardeis en in het tweede geval omdat er is geen waarde.

deleteis de operator waarmee u van o1(of een ander object waaraan een waarde is toegewezen aan de eigenschap p) naar o2op die manier: delete o1.p;.

De omgekeerde bewerking wordt uitgevoerd door simpelweg een waarde toe te kennen (undefinedin dit voorbeeld, maar het kan iets anders zijn) aan de eigenschap o1.p = undefined;.

Dus nee, ze zijn niet gelijkwaardig.


delete o.p;zal

  • verwijder de eigenschap pvan het object als het er een heeft

  • niets anders doen

o.p = undefined;zal

  • voeg een eigenschap ptoe aan het object als het er nog geen heeft en stel de waarde in op undefined

  • wijzig eenvoudig de waarde van de eigenschap als het object deze al heeft


Vanuit prestatieperspectief is deleteslechtomdat het de structuur van het object wijzigt(net als het toevoegen van een nieuwe eigenschap als je niet geïnitialiseerd in de constructor).

Terwijl het instellen van de waarde op undefinedde inhoud ook vrijgeeft, maar zonder de structuur te hoeven wijzigen.


Antwoord 8

Object is gewoon een boomweergave, dat wil zeggen dat in het geheugen de hoofdmap verwijst naar verschillende geheugenlocaties waar de sleutels van dat object zijn opgeslagen. en die locatie verwijst naar een andere locatie waar de werkelijke waarde van die sleutel is opgeslagen, of locaties waar de onderliggende sleutels zijn opgeslagen of locaties waar de array-waarden zijn opgeslagen.

Als je een sleutel van een object verwijdert met delete, wordt de koppeling tussen die sleutel en het bovenliggende object in feite verwijderd en worden de geheugenlocaties van de sleutel en de waarde ervan vrijgemaakt om andere informatie op te slaan.

Als u een sleutel probeert te verwijderen door undefined als waarde in te stellen, dan stelt u alleen de waarde in en verwijdert u die sleutel niet. Dat betekent dat de geheugenlocatie van de sleutel nog steeds is gekoppeld aan het bovenliggende object en de waarde als de sleutel niet is gedefinieerd.

Het gebruik van undefined in plaats van het gebruik van delete-trefwoord is een slechte gewoonte, omdat het de geheugenlocatie van die sleutel niet vrijgeeft.

Zelfs als de sleutel niet aanwezig is en u deze instelt als ongedefinieerd, wordt die sleutel gemaakt met de waarde undefined.

bijv.

var a = {};
a.d = undefined;
console.log(a); // this will print { d: undefined }

delete kan niet worden gebruikt met overgenomen eigenschappen omdat die eigenschap niet het deel is van dat onderliggende object.


Antwoord 9

Door een array te gebruiken in plaats van een object, kan ik aantonen dat verwijderen minder heapgeheugen gebruikt dan undefined.

Deze code zal bijvoorbeeld niet eindigen:

let y = 1;
let ary = [];
console.log("Fatal Error Coming Soon");
while (y < 4294967295)
{
    ary.push(y);
    ary[y] = undefined;
    y += 1;
}
console(ary.length);

Het geeft deze fout:

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory.

Dus, zoals je kunt zien, neemt undefinedeigenlijk heap-geheugen in beslag.

Als u echter ook het ary-item delete(in plaats van het alleen in te stellen op undefined), zal de code langzaam eindigen:

let x = 1;
let ary = [];
console.log("This will take a while, but it will eventually finish successfully.");
while (x < 4294967295)
{
    ary.push(x);
    ary[x] = undefined;
    delete ary[x];
    x += 1;
}
console.log(`Success, array-length: ${ary.length}.`);

Dit zijn extreme voorbeelden, maar ze maken een punt over deletedat ik nog nergens heb zien noemen.

Other episodes