ax vs ax = tanımsız


138

Bunlardan herhangi birini yaparken önemli bir fark var mı?

delete a.x;

vs

a.x = undefined;

nerede

a = {
    x: 'boo'
};

eşdeğer oldukları söylenebilir mi?

( "V8 deletedaha iyi kullanmamayı sever" gibi şeyleri dikkate almıyorum )


2
Silme işleci bir özelliği tamamen kaldırır. Bir özelliği tanımsız olarak ayarlamak değeri kaldırır. Bir özelliği null değerine ayarlamak, değeri null değerine değiştirir. İsterseniz mükemmel bir test: jsperf.com/delete-vs-undefined-vs-null/3
j08691

1
@ j08691 Nit: Değeri kaldırmaz. undefinedHala bir değer olarak atar ..

Bunu neden önemsediğiniz hakkında konuşmalısınız, o zaman cevap gerçek probleminize hitap edebilir.
Juan Mendes

Yanıtlar:


181

Eşdeğer değiller. Temel fark ayarın

a.x = undefined

a.hasOwnProperty("x")bunun hala doğru olacağı anlamına gelir ve bu nedenle, yine de bir for indöngüde veObject.keys()

delete a.x

bunun a.hasOwnProperty("x")yanlış döndüreceği anlamına gelir

Aynı olmaları, bir mülkün test edilerek var olup olmadığını söyleyememenizdir

if (a.x === undefined)

Bir mülkün var olup olmadığını belirlemeye çalışıyorsanız, yapmamanız gereken her zaman

// If you want inherited properties
if ('x' in a)

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

Prototip zincirinin ardından ( zzzzBov tarafından bahsedilir ) Calling , prototip zincirine çıkmasınadelete izin verirken, değeri undefined olarak ayarlamak, zincirleme prototiplerdeki özelliği aramayacaktır 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

Devralınan Mülkleri Silme Silmeye çalıştığınız mülk devralındıysa, deletebu özelliği etkilemez. Yani, deletemiras alınan özellikler değil , yalnızca nesnenin kendisinden özellikler siler.

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

Bu nedenle, bir nesnenin değerinin tanımlanmayacağından emin olmanız gerekiyorsa delete, özellik devralındığında çalışmazsa undefined, bu durumda onu (geçersiz kılmanız) gerekir . Kontrol eden yer kullanmazsa hasOwnProperty, ancak kontrol eden her yerde kullanacağını varsaymak muhtemelen güvenli olmazhasOwnProperty


1
"x" in aaynı zamanda truebirincisiyle ve falseikincisiyle birlikte dönecektir . Çıktısı Object.keysda farklı olacaktır.
lonesomeday

neden tanımsız olup olmadığını kontrol etmem gerektiğini söylüyorsun? benim için yeterince makul görünüyor.
bevacqua

@Nico Çünkü bu size bir mülk olup olmadığını söylemez. Hiç kullanma. Ancak kontrol undefinedediyorsanız, if (a.x)sayılar ve 0 geçerli olmadığı sürece de kontrol edebilirsiniz
Juan Mendes

33

Soruyu açıklamak için:

Are delete a.xve a.x = undefineddengi?

Hayır.

Birincisi anahtarı değişkenten kaldırır, daha sonra anahtarı bir değere ayarlar undefined. Bu, nesnelerin özellikleri üzerinde yineleme yaparken ve hasOwnPropertykullanıldığında bir fark yaratır .

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

Ayrıca, prototip zinciri söz konusu olduğunda bu önemli bir fark yaratacaktır.

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'

2
+1 deletePrototip zincirine çıkmasına izin vermek için harika bir nokta
Juan Mendes

4

Eğer a.xbir ayarlayıcı fonksiyonudur, a.x = undefinedoysa işlevini çağırır delete a.xişlevini aramayacak.


3

Evet, bir fark var. delete a.xX kullanırsanız , a'nın bir özelliği değildir, ancak kullanırsanız a.x=undefinedbir özelliktir ancak değeri tanımsızdır.


2

İsimler biraz kafa karıştırıcı. a.x = undefinedsadece özelliği olarak ayarlar undefined, ancak özellik hala oradadır:

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

delete aslında siler:

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

1

Düğümden gelen bu REPL farkı göstermelidir.

> 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

1

Eminim var o1 = {p:undefined};ve arasındaki farkı görebilirsiniz var o2 = {};.

Her iki durumda da o.polacak undefinedama bu çünkü birinci durumda, bu kadar değer ve ikinci durumda çünkü hiçbir değer yoktur .

deleteEğer aldığım sağlayan operatörüdür o1(veya atanmış bir değere sahiptir başka nesne pözellik) o2bu şekilde: delete o1.p;.

Ters işlem, undefinedözelliğe bir değer ( bu örnekte ancak başka bir şey olabilir) atanarak yapılır o1.p = undefined;.

Yani hayır , eşdeğer değiller.


delete o.p; niyet

  • özelliği pvarsa nesneden kaldır

  • başka bir şey yapma

o.p = undefined; niyet

  • phenüz bir özelliği yoksa nesneye bir özellik ekleyin ve değeriniundefined

  • nesne zaten varsa özelliğin değerini değiştirmeniz yeterlidir


Performans açısından bakıldığında, deletebir kötü çünkü nesnenin yapısını değiştirir (sadece yapıcı bunu başlatılmadı varsa yeni bir özellik ekleme gibi).

Oysa değeri undefined, içeriği serbest bırakacak şekilde ayarlamak, ancak yapıyı değiştirmeye zorlamaksızın.


1

Nesne basitçe bir ağaç temsilidir, yani bellekte kök, o nesnenin anahtarlarının depolandığı çeşitli bellek konumlarına işaret eder. ve bu konum, söz konusu anahtarın gerçek değerinin depolandığı başka bir konumu veya alt anahtarların depolandığı konumları veya dizi değerlerinin depolandığı konumları gösterir.

Delete komutunu kullanarak bir nesneden herhangi bir anahtarı sildiğinizde, aslında o anahtar ile üst nesnesi arasındaki bağlantıyı siler ve anahtarın bellek konumları ile değeri başka bir bilgiyi saklamak için serbest bırakılır.

Herhangi bir anahtarı değer olarak tanımsız olarak ayarlayarak silmeye çalıştığınızda, o anahtarı silmemek yerine yalnızca değerini ayarlarsınız. Bu, anahtarların bellek konumunun hala üst nesnesiyle ve anahtar tanımsızsa değerle bağlantılı olduğu anlamına gelir.

Delete anahtar sözcüğü yerine undefined kullanmak kötü bir uygulamadır, çünkü o anahtarın bellek konumunu serbest bırakmaz.

Anahtar mevcut olmasa ve tanımsız olarak ayarlasanız bile, o anahtar değerle oluşturulur undefined.

Örneğin

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

delete, devralınan özelliklerle çalışamaz, çünkü bu özellik o alt nesnenin parçası değildir.


1
Daha yeni motorların anahtarları silmemeyi tercih ettiğini unutmayın, çünkü bunu yaptığınızda motorun bunun için yeni bir sınıf oluşturması ve "sınıf" referanslı olduğu her yerde güncellemesi gerekir.
Juan Mendes

@JuanMendes, lütfen herhangi bir referans verebilir misiniz.
Laxmikant Dange

3
Bkz. Delete anahtar sözcüğünü kullanma, bir nesnenin v8 optimizasyonlarını etkiler mi? TL; DR as a general rule of thumb, using 'delete' makes thing slower.ve developers.google.com/v8/design To reduce the time required to access JavaScript properties, V8 does not use dynamic lookup to access properties. Instead, V8 dynamically creates hidden classes behind the scenes. In V8, an object changes its hidden class when a new property is added. ve son olarak smashingmagazine.com/2012/11/…
Juan Mendes

1

Nesne yerine bir dizi kullanarak, silme işleminin tanımsızdan daha az yığın bellek kullandığını gösterebilirim.

Örneğin, bu kod bitmez:

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

Bu hatayı üretir:

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

Gördüğünüz gibi undefinedaslında yığın bellek kaplıyor.

Ancak, deleteary öğesini de (yalnızca ayarlamak yerine) yaparsanız undefined, kod yavaşça biter:

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}.`);

Bunlar aşırı örneklerdir, ancak deletekimsenin hiçbir yerde bahsetmediğini bir noktaya işaret ediyorlar .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.