JavaScript'teki Nesneleri Silme


359

JavaScript'in deleteoperatörü ile biraz kafam karıştı . Aşağıdaki kod parçasını alın:

var obj = {
    helloText: "Hello World!"
};

var foo = obj;

delete obj;

Bu kod parçası yürütüldükten sonra, objolduğu nullancak fooyine de tam gibi bir nesne anlamına gelmektedir obj. Bu nesnenin fooişaret ettiği aynı nesne olduğunu tahmin ediyorum .

Bu beni şaşırttı, çünkü yazmanın sadece değişkeni değil, bellekte işaret eden delete objnesneyi objsilmesini bekliyordum obj.

Bunun nedeni JavaScript'in Çöp Toplayıcısının tutma / bırakma esasına göre çalışmasıdır, böylece nesneyi gösteren başka değişkenler olmasaydı bellekten kaldırılır mı?

(Bu arada, testlerim Safari 4'te yapıldı.)




2
Yukarıdaki bağlantı şöyle olmalıdır: perfectionkills.com/understanding-delete
johnmdonahue

1
@Steve Harrison silme senin durumda bir nesne anahtarı çıkarma işleminde javascript silme kullanımda bir nesneyi silmek için değil var obj = { helloText: "Hello World!" }; var foo = obj; delete obj;çek nesne silinmez obj: Silme kullanım delete obj.helloTextve daha sonra kontrolfoo now foo is an empty object
Umeyr Ahmed

2
@UmairAhmed, Serbest çeviri: """ delete. Javascript nesneleri silmek için değil delete. Senin durumunda bir nesne anahtarı kaldırmak için kullanılır var obj = { helloText: "Hello World!" }; var foo = obj; delete obj;. Denetlemek, nesne silinmez obj. Çalıştırın Sonraki delete obj.helloTextve bunu görebilirsiniz fooboş artık puan "" "
Pacerier

Yanıtlar:


448

Silme işleci yalnızca bir referansı siler, bir nesnenin kendisini asla silmez. Nesnenin kendisini silmiş olsaydı, C ++ silme gibi diğer referanslar da sarkabilir. (Ve bunlardan birine erişmek çökmeye neden olur. Hepsini null yapmak için, silerken fazladan iş veya her nesne için fazladan bellek anlamına gelir.)

Javascript çöp toplandığından, nesneleri kendileri silmenize gerek yoktur - bunlara artık başvurmanın bir yolu olmadığında kaldırılırlar.

Bunlarla işiniz bittiğinde bir nesneye yapılan referansları silmek yararlı olabilir, çünkü bu, çöp toplayıcısına geri kazanılabilecek şeyler hakkında daha fazla bilgi verir. Başvurular büyük bir nesneye kalırsa, programınızın geri kalanı o nesneyi kullanmasa bile bu durumun geri alınmamasına neden olabilir.


23
deleteAnahtar kelime sadece bir nesnenin özelliklerini değil, değişkenler için çalışır. perfectionkills.com/understanding-delete
Alex Mund

1
@AlexJM Evet, Guffa'nın bir sonraki cevabı (ve yorumları) bunu ayrıntılı olarak tartışıyor.
Jesse Rusak

1
Bir nesnenin özelliği başka bir nesne olabilir. Örneğin; var obj = {a: {}}; delete obj.a;
Alex Mund

2
Ama ... değişkenler aslında özellikleri değil windowmi?
RedClover

3
@ Soaku yerel değişkenler değil. (örn. ile beyan edilenler var)
Jesse Rusak

162

deleteKomut düzenli değişkenler, sadece özelliklerine etkisi yoktur. Komuttan sonra deleteözellik değere nullsahip değil, hiç yok.

Özellik bir nesne başvurusuysa, deletekomut özelliği siler ancak nesneyi silmez. Çöp toplayıcı, nesneye başka bir referansı yoksa nesne ile ilgilenir.

Misal:

var x = new Object();
x.y = 42;

alert(x.y); // shows '42'

delete x; // no effect
alert(x.y); // still shows '42'

delete x.y; // deletes the property
alert(x.y); // shows 'undefined'

(Firefox'ta test edildi.)


39
Bu, global kapsamda yürütülürse, xdeğişkeniniz yalnızca global windownesne üzerindeki bir özellik haline gelir delete x;ve xdeğişkeni gerçekten tamamen kaldırır .
Crescent Fresh

18
@crescentfresh: Yalnızca dolaylı olarak bildirilmişse bir özelliktir. Örnekte olduğu gibi açıkça bildirilirse, genel bir değişkendir ve silinemez.
Guffa

4
@Tarynn: Anlıyorum, problem burada. Bunu konsolda yaparsanız, bazı nedenlerden dolayı xbazı tarayıcılarda uygun bir değişken değil, windownesnede bir özellik olacaktır . Bu elbette konsolla ilgili bir sorundur ve kodun normal olarak nasıl yürütüldüğünü yansıtmaz.
Guffa

2
@Guffa Bir sürü araştırmadan sonra, muhtemelen oy vermek için yeterli temsilciye sahip olmadığım iyi bir şey olduğunu kabul etmeliyim. En içten özür dilerim ve bana neler olduğunu göstermek için zaman ayırdığınız için teşekkür ederiz ... İşte derinlemesine bir açıklama: perfectionkills.com/understanding-delete/#firebug_confusion
Tarynn 28:13

2
@chao: Anlıyorum. Tarynn ile aynı sorunu yaşıyorsanız (önceki yorumlara bakın). Bunu konsolda yaptığınızda, gerçek koddakiyle aynı şekilde çalışmaz.
Guffa

56

"dolaylı olarak bildirilen değişkenler" genel nesnenin özellikleridir, bu nedenle silme özelliği herhangi bir özellikte olduğu gibi üzerlerinde çalışır. Var ile bildirilen değişkenler yok edilemez.


53
Var'ın bu kadar kötü olduğunu hiç farketmedim.
Gavin

1
Bu harika bir nokta ve bir JS gotcha. İnsanlar pencere değişkenlerini silmeye alışırlar ve sonra neden yerel değişkenlerle aynı şeyi yapamayacaklarını merak ederler.
welbornio

2
Aynı şey geçerli let.
Pacerier


4

delete java Script'teki bir nesneyi silmek için kullanılmaz.

deletebir object keydavanızı çıkarmak için kullanılır

var obj = { helloText: "Hello World!" }; 
var foo = obj;
delete obj;

nesne silinmedi kontrol obj hala aynı değerleri almak kullanımı silmek:

delete obj.helloText

ve sonra obj, fooher ikisinin de boş nesne olduğunu kontrol edin .


2

Bu konunun ışığında ilginç olduğunu düşündüğünüz bir jsperf buldum . (resmi tamamlamak için etrafta tutmak kullanışlı olabilir)

Delete , null ayarı ve undefined ayarını karşılaştırır .

Ancak, özelliği birçok kez sildiğinizde / ayarladığınızda durumu test ettiğini unutmayın.



1

IE 5 ile 8 arasında bir ana bilgisayar nesnesinin (Window, Global, DOM vb.) Üzerinde delete kullanmanın TypeError "nesnesi bu eylemi desteklemiyor" hatası verdiği bir hata vardır.

var el=document.getElementById("anElementId");
el.foo = {bar:"baz"};
try{
    delete el.foo;
}catch(){
    //alert("Curses, drats and double double damn!");
    el.foo=undefined; // a work around
}

Daha sonra bu tesiste anlam tam değer kullanımı vardır nereye kontrol etmek gerekirse el.foo !== undefined, çünkü "foo" in el her zaman IE gerçek dönecektir.

Gerçekten kaybolmak için gerçekten ihtiyacınız varsa ...

function hostProxy(host){
    if(host===null || host===undefined) return host;
    if(!"_hostProxy" in host){
       host._hostproxy={_host:host,prototype:host};
    }
    return host._hostproxy;
}
var el=hostProxy(document.getElementById("anElementId"));
el.foo = {bar:"baz"};

delete el.foo; // removing property if a non-host object

host api ile host nesnesini kullanmanız gerekiyorsa ...

el.parent.removeChild(el._host);

1

Aynı cevabı aramamda bu makaleye rastladım. obj.pop()Yaptığım şey, nesneyi yeniden kullanabilmem için nesnemdeki tüm depolanmış değerleri / nesneleri dışarı atmak . Bunun kötü bir uygulama olup olmadığından emin değilim. Bu teknik, kodumu Chrome Dev araçlarında veya FireFox Web Konsolunda test etmem için kullanışlı oldu.


1

Bu iş benim için, iyi bir uygulama olmamasına rağmen. Yalnızca nesnenin ait olduğu ilişkili tüm öğeyi siler.

 for (element in homeService) {
          delete homeService[element];
  }

en iyi uygulama nedir? Delete operatörünün nesne özelliklerini silmek için en iyi yöntem olmadığını okuduğumu hatırlıyorum. Bunu Crockford'un JavaScript kitabında okuduğuma inanıyorum, ancak şu anda kazamıyorum.
zero_cool

0

Değişken olarak ayarlamak null, DOM öğeleri ve Javascript kapsamları arasında dairesel referanslar da dahil olmak üzere tüm tarayıcılardaki nesnelere yapılan başvuruların kesildiğinden emin olur. deleteKomutu kullanarak , Çöp koleksiyonunun bir sonraki çalıştırmasında temizlenecek nesneleri işaretliyoruz, ancak aynı nesneyi referans alan birden fazla değişken varsa, tek bir değişkeni silmek nesneyi serbest bırakmayacak, sadece bu değişken arasındaki bağlantıyı kaldıracaktır. nesne. Ve Çöp koleksiyonunun bir sonraki çalıştırmasında yalnızca değişken temizlenir.

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.