Bir JavaScript değişkenini nasıl kaldırabilirim?


592

Ben windowzaten önceki bir komut dosyası tarafından doldurulmuş JavaScript (aslında bir özellik, ama önemli olduğunu sanmıyorum) küresel bir değişken var ama değerini görmek için daha sonra çalışacak başka bir komut istemiyorum ya da hatta tanımladı.

Koydum some_var = undefinedve test etmek için çalışıyor typeof some_var == "undefined"ama gerçekten bunun doğru yolu olduğunu düşünmüyorum.

Ne düşünüyorsun?

Yanıtlar:


454

deleteOperatör, nesnenin özelliği kaldırır. Bir değişkeni kaldıramaz. Dolayısıyla sorunun cevabı, global değişkenin veya özelliğin nasıl tanımlandığına bağlıdır.

(1) Birlikte oluşturulmuşsa varsilinemez.

Örneğin:

var g_a = 1; //create with var, g_a is a variable 
delete g_a; //return false
console.log(g_a); //g_a is still 1

(2) Olmadan oluşturulursa varsilinebilir.

g_b = 1; //create without var, g_b is a property 
delete g_b; //return true
console.log(g_b); //error, g_b is not defined

Teknik Açıklama

1. Kullanma var

Bu durumda referans g_a, ECMAScript spesifikasyonunun geçerli kapsama bağlı olan " VariableEnvironment " olarak adlandırdığı şeyde oluşturulur - bu, bir fonksiyonun içinde kullanılması durumunda bir fonksiyon yürütme bağlamı varolabilir (ancak biraz daha karmaşık olabilir) dikkate aldığınızda let) veya "global" kod söz konusu olduğunda , VariableEnvironment global nesneye eklenir (genellikle window).

VariableEnvironment içindeki referanslar normal olarak silinebilir değildir - ECMAScript 10.5'te ayrıntılı olarak açıklanan işlem bunu ayrıntılı olarak açıklar, ancak kodunuz bir evalbağlamda (tarayıcı tabanlı geliştirme konsollarının kullandığı) kullanılmadıkça, bildirilen değişkenlerin varyapamayacağını söylemeye yeter silinecek.

2. Kullanmadan var

varAnahtar kelimeyi kullanmadan bir ada bir değer atamaya çalışırken , Javascript, ECMAScript spesifikasyonunun " LexicalEnvironment " olarak adlandırdığı öğede adlandırılmış başvuruyu bulmaya çalışır ve temel fark LexicalEvironment'in iç içe geçmiş olmasıdır - bu bir LexicalEnvironment'ın bir üst öğesi ( ECMAScript spesifikasyonunun "dış ortam referansı" dediği ve Javscript referansı bir LexicalEenvironment içinde bulamadığında , üst LexicalEnvironment ( 10.3.1 ve 10.2.2.1'de detaylandırıldığı gibi) içine bakar . Üst düzey LexicalEnvironment " global ortam ""ve bu, başvuruların genel nesnenin özellikleri olması nedeniyle genel nesneye bağlıdır. Dolayısıyla var, geçerli kapsamdaki bir anahtar sözcük veya herhangi bir dış kapsam kullanılarak bildirilmeyen bir ada erişmeye çalışırsanız , Javascript sonunda bir özellik getirecektir bir windownesnenin o referans olarak hizmet etmek. Daha önce öğrendiğiniz üzere, nesneler üzerinde özellikler silinebilir.

notlar

  1. varBeyanların "kaldırıldığını" hatırlamak önemlidir - yani her zaman bulundukları kapsamın başlangıcında olduğu kabul edilir - bir varifadede yapılabilecek değer başlangıcı olmasa da - olduğu yerde kalır . Aşağıdaki kodda Yani, abir referans olduğunu VariableEnvironment değil windowmülk ve onun değer olacaktır 10kodun sonuna:

    function test() { a = 5; var a = 10; }

  2. Yukarıdaki tartışma "katı mod" etkin olmadığındadır. Arama kuralları "katı mod" kullanıldığında biraz farklıdır ve "katı mod" olmadan pencere özelliklerine çözümlenecek sözcüksel başvurular, "katı mod" altında "bildirilmemiş değişken" hatalarını yükseltir. Bunun nerede belirtildiğini gerçekten anlamadım, ancak tarayıcıların nasıl davrandığı.


8
Söyledikleriniz yaygın bir yanlış anlamadır ama aslında yanlıştır - Javascript'te "global değişkenler" yoktur. Açık bir kapsam olmadan tanımlanmış değişkenler ( varbir işlev dışında kullanmak gibi ), web tarayıcılarında bulunan "global nesnenin" özellikleridir window. Yani - var a = 1; delete window.a; console.log(a);değişkeni başarıyla siler ve son satırın bir referans hatası vermesine neden olur.
Guss

7
@Guss, kodunuz 1 var a = 1; delete window.a; console.log(a);gösterir.
Dayong

5
Google Chrome v36 kullanıyorum. Diğer tarayıcılarda test ettim. Görünüşe göre tutarlı çapraz tarayıcılar değil. Chrome ve Opera 1 görüntüledi, bilgisayarımdaki Firefox, Safari ve IE 11 bir hata verdi.
Dayong

3
Tamam, benim hatam. Bkz. Ecma-international.org/ecma-262/5.1/#sec-10.5 (alt noktalar 2 ve 8.c.ii): Testimi geliştirici konsolunda çalıştırırken, genellikle "eval bağlamı" olarak kabul edilir (belki de Chrome'da değil), bu nedenle bir hata ortaya çıkar. Gerçek bir belgenin genel bağlamındaki aynı kod 1, tüm tarayıcılarda doğru şekilde çıkacaktır . Gerçek belgelerde çalışırken, kod örnekleriniz doğrudur. Cevabınızı doğru olarak seçtim, ancak açıklamayı window.a = 1; delete window.a;ve muhtemelen mekanizmayı içerecek şekilde düzenleyebilirseniz memnun olurum . Eğer sakıncası yoksa bunu da yapabilirim.
Guss

2
@KlaiderKlai evet. İşlev kapsamındaki değişkenler, işlev her yürütüldüğünde oluşturulur ve yok edilir. Muhtemelen kapatma bir istisnadır.
Dayong

278

@ scunlife'ın cevabı işe yarayacak, ancak teknik olarak

delete window.some_var; 

hedef bir nesne özelliği olmadığında, silme işleminin hiç işlem yapılmaması gerekir. Örneğin,

(function() {
   var foo = 123;
   delete foo; // wont do anything, foo is still 123
   var bar = { foo: 123 };
   delete bar.foo; // foo is gone
}());

Ancak global değişkenler aslında window nesnesinin üyeleri olduğu için çalışır.

Prototip zincirleri söz konusu olduğunda, silme özelliğini kullanmak daha karmaşık hale gelir, çünkü özelliği prototipi değil, yalnızca hedef nesneden kaldırır. Örneğin,

function Foo() {}
Foo.prototype = { bar: 123 };
var foo = new Foo();
// foo.bar is 123
foo.bar = 456;
// foo.bar is now 456
delete foo.bar;
// foo.bar is 123 again.

Yani dikkatli ol.

EDIT: Cevabım biraz yanlış (sonunda "Yanılgıları" bakın). Bağlantı, tüm ayrıntılı ayrıntıları açıklar, ancak özet, tarayıcılar arasında ve sildiğiniz nesneye bağlı olarak büyük farklılıklar olabileceğidir. delete object.somePropgenellikle güvenli olduğu sürece object !== window. varDoğru koşullar altında yapabilmenize rağmen, beyan edilen değişkenleri silmek için hala kullanmam .


14
Bu ilginç makaleye bağlantı için teşekkürler @jedierikb. daha özel olarak , yazarın, noah'ın "delete ifadesinin bir op olması gerektiğini" belirttiği bu makalenin < perfectionkills.com/understanding-delete/#misconceptions > bu bölüme , neden yanlış olduğu konusunda mükemmel bir açıklama ile birlikte yanlıştır. . (Elçiyi vurma!)
Rob Wells

2
Gözden geçirilmiş yanıtın son cümlesiyle ilgili olarak, bildirilen değişkenleri silebileceğiniz tek koşul, değişkenin bildirildiği varzamandır eval.
Stephen Booher

1
In Bu durumda , silme deyimi hiç bir şey yapmak için görünmüyor. Burada neler oluyor?
Anderson Green

@ AndersonGreen — decalred global değişkenleri DontDelete bayrağıyla oluşturulur, bu nedenle silinebilir değil. Bu kod tam olarak beklendiği gibi davranır.
RobG

35

Değişkeni dolaylı olarak bildiriyorsanız var, doğru yol kullanmak olacaktır delete foo.

Ancak, silindikten sonra, bunu eklenme gibi bir işlemde kullanmaya çalışırsanız, ReferenceErrorbildirilmemiş, tanımlanmamış bir tanıtıcıya dize ekleyemeyeceğiniz için a atılır. Misal:

x = 5;
delete x
alert('foo' + x )
// ReferenceError: x is not defined

Bazı durumlarda yanlış, boş veya tanımsız olarak atanması daha güvenli olabilir, böylece bildirilir ve bu tür bir hata atmaz.

foo = false

Not ECMAScript'te olduğunu null, false, undefined, 0, NaN, veya ''tümüne değerlendirirsiniz false. Sadece !==operatörü kullanmadığınızdan emin olun, bunun yerine !=booleans için tip kontrolü yaparken ve kimlik kontrolü istemiyorsanız ( ve öyle nullolur ).== falsefalse == undefined

Ayrıca delete, referansların "silinmediğini", yalnızca nesnenin üzerindeki özelliklerin, örneğin:

bah = {}, foo = {}; bah.ref = foo;

delete bah.ref;
alert( [bah.ref, foo ] )
// ,[object Object] (it deleted the property but not the reference to the other object)

Birlikte bir değişken bildirdiyseniz var, onu silemezsiniz:

(function() {
    var x = 5;
    alert(delete x)
    // false
})();

Gergedan'da:

js> var x
js> delete x
false

Ayrıca önceden tanımlanmış bazı özellikleri de silemezsiniz Math.PI:

js> delete Math.PI
false

deleteHerhangi bir dilde olduğu gibi bazı tuhaf istisnalar vardır, yeterince önemsiyorsanız okumalısınız:


Tüm detayları içeren eksiksiz cevap için teşekkürler. Bunu bunun için işaretledim, ancak Noah'ın cevabını kabul ettim çünkü basit bir soru kısalığı tamamlanmasından daha önemli olduğuna inanıyorum. Tekrar - bu cevapta yaptığınız harika çalışmalar için teşekkürler.
Guss

30
some_var = null;

//or remove it..
delete some_var;

11
Bu kodun kapsamı bir işlevse bu çalışmaz. Doğru çözüm için @ noah'ın cevabına bakınız.
Roatin Marth

1
Cevabınız için teşekkürler, ama Noah'ın cevabını kabul ettim çünkü tuzaklarını daha iyi açıklıyor delete.
Guss

3
Endişeye gerek yok ... Ben "hızlı n kirli" basit bir cevap verdi - @noah "diğer" davaları için tüm detayları ekledi böylece kredi de hak ediyor. ;-)
scunliffe

7
Bu doğru değil. deleteyalnızca bir mülk için çalışır. nullDeğişkenin ayarlanması hala mevcuttur.
Derek 朕 會 功夫

1
Bu cevap, "if (some_var) {..}" ile kontrol ettiğiniz en olası durum için yeterince iyi
BearCode

16

TLDR: (olmadan basit değişkenler tanımlanır var, let, const) ile silinebilir delete. Eğer kullanırsanız var, let, const- Birlikte ne silinemedi deletene de sahip Reflect.deleteProperty.

Chrome 55:

simpleVar = "1";
"1"
delete simpleVar;
true
simpleVar;
VM439:1 Uncaught ReferenceError: simpleVar is not defined
    at <anonymous>:1:1
(anonymous) @ VM439:1
var varVar = "1";
undefined
delete varVar;
false
varVar;
"1"
let letVar = "1";
undefined
delete letVar;
true
letVar;
"1"
const constVar="1";
undefined
delete constVar;
true
constVar;
"1"
Reflect.deleteProperty (window, "constVar");
true
constVar;
"1"
Reflect.deleteProperty (window, "varVar");
false
varVar;
"1"
Reflect.deleteProperty (window, "letVar");
true
letVar;
"1"

FF Nightly 53.0a1 aynı davranışı gösterir.


Cevabınız teknik olarak doğrudur, bu yüzden bir puan alırsınız, ancak yazdığınız her şey, ECMAScript spesifikasyonlarına çok daha fazla ayrıntı ve referansla seçilen cevap tarafından kapsanır - gelecekte yayınlamadan önce mevcut cevabı incelemek yararlı olacaktır.
Guss

5
Kabul. Ancak tek vardavadan bahsedildi . Bana gelince o test ve hisse ilginçti letve constolguların yanı. Ancak, not için teşekkürler. Bir dahaki sefere daha spesifik olmaya çalışacağız.
17'de Serj.

4

ECMAScript 2015, Reflect API'sini sunar. Reflect.deleteProperty () ile nesne özelliğini silmek mümkündür :

Reflect.deleteProperty(myObject, 'myProp');
// it is equivalent to:
delete myObject.myProp;
delete myObject['myProp'];

Genel windownesnenin özelliğini silmek için :

Reflect.deleteProperty(window, 'some_var');

Bazı durumlarda özellikler silinemez (özellik yapılandırılamadığında) ve sonra bu işlev geri döner false(ayrıca operatörü de sil ). Diğer durumlarda true:

Object.defineProperty(window, 'some_var', {
    configurable: false,
    writable: true,
    enumerable: true,
    value: 'some_val'
});

var frozen = Object.freeze({ myProperty: 'myValue' });
var regular = { myProperty: 'myValue' };
var blank = {};

console.log(Reflect.deleteProperty(window, 'some_var')); // false
console.log(window.some_var); // some_var

console.log(Reflect.deleteProperty(frozen, 'myProperty')); // false
console.log(frozen.myProperty); // myValue

console.log(Reflect.deleteProperty(regular, 'myProperty')); // true
console.log(regular.myProperty); // undefined

console.log(Reflect.deleteProperty(blank, 'notExistingProperty')); // true
console.log(blank.notExistingProperty); // undefined

Katı modda çalıştırıldığında deletePropertyişlev ve deleteoperatör arasında bir fark vardır :

'use strict'

var frozen = Object.freeze({ myProperty: 'myValue' });

Reflect.deleteProperty(frozen, 'myProperty'); // false
delete frozen.myProperty;
// TypeError: property "myProperty" is non-configurable and can't be deleted

4

Değişkenler, basit özelliklerin aksine [[Yapılandırılabilir]] özelliğine sahiptir, bu da silme operatörü aracılığıyla bir değişkeni kaldırmak imkansızlığı anlamına gelir . Ancak, bu kuralın etkilemediği bir yürütme bağlamı vardır. Bu ise Eval bağlam: orada [[Ayarlanabilir]] nitelik değişkenler için ayarlanmamıştır.



3

Herkesin yazdıklarına ek olarak, deleteboole döndürdüğünü de unutmayın . Silme işleminin başarılı olup olmadığını söyleyebilir.

Chrome'da test edildi, hariç her şey letsilinebilirdi. ne zaman deleteiade trueaslında onları kaldırıldı:

implicit_global = 1;
window.explicit_global = 1;
function_set = function() {};
function function_dec() { };
var declared_variable = 1;
let let_variable = 1;

delete delete implicit_global; // true, tested on Chrome 52
delete window.explicit_global; // true, tested on Chrome 52
delete function_set; // true, tested on Chrome 52
delete function_dec; // true, tested on Chrome 52
delete declared_variable; // true, tested on Chrome 52
delete let_variable; // false, tested on Chrome 78

Her zaman doğru değil. Özellikle Chrome'da. Firefox her şeyi doğru döndürüyor. Başka tarayıcılarda test yapmadı. Gelince letvars ve constdeğişken silindi ama değil araçlarının gerektiğini şeyin gerçek döndürüyor vars. Hem Chrome'da hem de FF'de kontrol edebilirsiniz. Chrome değilken FF doğru değerleri döndürüyor gibi görünüyor. Bu yüzden gerçekten ona güvenebileceğinizden emin olun. Bir bakalım:let letVar = "1"; undefined delete letVar; true letVar "1" typeof letVar; "string" const constVar="1"; undefined delete constVar; true constVar; "1" typeof constVar; "string"
Serj.

1
Jedierikb'ın aşağıda belirtildiği gibi, kangax perfectionkills.com/understanding-delete tarafından deleteoperatörün neden ve nasıl çalıştığını çoğunlukla anlatan mükemmel bir makale vardır . Ancak, işlevlerle neden tam anlamıyla oposite durumun tanımlanmadığı. Yazık. Bununla birlikte, değişkenlerle ilgili olarak işler çok daha net görünmeye başlar.
Serj. Tarafından

2

İlk kullanım sırasında bir değişkeni bildirdiyseniz (var x; ile) silemezsiniz. Ancak, x değişkeniniz komut dosyasında ilk olarak bir bildirimde bulunmadıysa, delete operatörünü (delete x;) kullanabilirsiniz ve değişkeniniz silinir, bir dizinin bir öğesini silmeye veya bir nesnenin bir özelliğini silmeye çok benzer .


1

Biraz kafam karıştı. İstediğiniz tek şey bir değişken değerinin başka bir komut dosyasına geçmemesi için, değişkenin kapsamdan silinmesine gerek yoktur. Değişkeni geçersiz kılınız ve sonra null olup olmadığını açıkça kontrol ediniz. Neden değişkeni kapsamdan silme sorununu yaşıyoruz? Geçersiz kılan bu sunucu hangi amacı yapamaz?

foo = null;
if(foo === null) or if(foo !== null)

Gereksinim, benim kontrolüm altında olmayan sipariş betiğinin, değişkenin var olduğunu göremeyeceğidir - özellikle OP durumu için, hedef komut dosyasının nulltetiklemek istemediğim değer için bir davranışı vardır .
Guss

Bu sorunun üretimi sırasında hiçbir "arka uç" kötüye kullanılmamıştır. Bunlar sadece bu tek bir komut dosyası dışında hiçbir şey kontrol yok bir web sitesinde komut dosyaları bir çift vardır.
Guss

Her iki komut dosyası da aynı belgede mi yoksa birinin diğerini yüklemesi için çağırdığı ayrı belgelerde mi? Sipariş komut dosyasından ve hedef komut dosyasından bahsettiniz. Bir değişken bir get / post değişkeni ile başka bir komut dosyasına geçiriliyorsa, o zaman herhangi bir javascript ellerini almadan önce arka uçta silmek istiyorum. Php bunun bir örneği gibi bir şey olurdu. <?php if(isset($_POST['somevariable']) unset($_POST['somevariable']); if(isset($_GET['somevariable']) unset($_GET['somevariable']); ?>
designdrumm

Anlıyorum. Eğer null için kontroller ve dengeler varsa, o zaman bir değere ayarlamak hedef betiği ile bir şey yapmaz daha mantıklı görünüyor sonra bir değişken kapsamdan silmek, ama cevap var, bu yüzden atın bırak izin verir. Yanıtlarınız için teşekkürler.
designdrumm

Kısa bir soru. Sizinkinden sonra çağrılan ama sizin kontrolünüzde olmayacak ama yine de bu değişkene ihtiyaç duyacak bir komut dosyası olacak mı? Öyleyse, değişkenin kapsamdan silinmesi kötü bir fikirdir.
designdrumm
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.