değişken === tanımsız ve typeof değişken === “tanımsız”


300

JQuery Çekirdek Stil Kuralları değişken tanımlanmış olup olmadığını kontrol etmek için iki farklı yol göstermektedir.

  • Global Değişkenler: typeof variable === "undefined"
  • Yerel Değişkenler: variable === undefined
  • Özellikleri: object.prop === undefined

JQuery neden global değişkenler için bir yaklaşım, yerliler ve özellikler için başka bir yaklaşım kullanıyor?


JQuery'nin her iki yaklaşımı neden kullanacağı sorusuna cevap veremiyorum, ancak Javascript'in bu iki şeyin kurnazca farklı olduğu anlamına gelen bazı ilginç tuhaflıkları var. Çoğu zaman önemli olmamalı (yani kodunuz aklı başında ise), ancak yine de farklılıklar var: Yazmak için buraya bakın - wtfjs.com/2010/02/15/undefined-is-mutable
Spudley

2
@Struppi'nin işaret ettiği gibi, jQuery'nin en dıştaki işlevi undefined adlı bir argümana sahiptir. JQuery içinde, foo === undefineddeli kodu ile değiştirilmiş olabilecek global (window.undefined) yerine undefined'in yerel kopyasını kontrol ediyor. Undefined değişebilir olması kesinlikle kayda değer ve yaptığınız için memnunum. (+1)
Patrick McElhaney

1
Bu makale için şu anki bağlantı wtfjs.com/wtfs/2010-02-15-undefined-is-mutable
enigment

Yanıtlar:


366

Bildirilmeyen değişkenler için, typeof foodize değişmezini döndürürken "undefined"kimlik denetimi "foo tanımlı değil"foo === undefined hatasını tetikler .

Yerel değişkenler için (bir yerlerde bildirildiğini bildiğiniz ), böyle bir hata oluşmaz, dolayısıyla kimlik kontrolü yapılır.


3
@goreSplatter Şimdi silemezsiniz. :-) Seçmek zordu, ancak sorunun ifade edildiği şekliyle, bu cevap daha uygun. Genel olarak nasıl tanımlandığına (benim gibi) ilgi duyan herkes diğer cevaplara da bakmalıdır, özellikle @ Tim's.
Patrick McElhaney

4
typeof foo; // -> "undefined"İlkel değer değil, bir dize olduğunu vurgulamak için tırnak işaretleri ( ) eklerdim undefined.
c24w

117

Her typeof foo === "undefined"yerde kullanmaya devam ederdim . Bu asla yanlış gidemez.

Neden jQuery iki farklı yöntem önerdiğini düşünmek onlar kendi undefineddeğişken jQuery kodu içinde yaşayan işlevi içinde tanımlamak olduğunu, bu nedenle bu işlevi undefineddışında dış kurcalamak güvenlidir. Ayrıca bir yerlerde birisinin iki farklı yaklaşımı kıyasladığını ve bunun foo === undefineddaha hızlı olduğunu keşfettiğini ve bu nedenle bunun yoluna karar verdiğini hayal ediyorum . [GÜNCELLEME: yorumlarda belirtildiği gibi, karşılaştırma undefinedda biraz daha kısadır, bu da dikkate alınabilir.] Bununla birlikte, pratik durumlardaki kazanç tamamen önemsiz olacaktır: bu kontrol asla, asla herhangi bir darboğaz olmayacak ve ne kaybetmeniz önemlidir: karşılaştırma için bir ana bilgisayar nesnesinin bir özelliğini değerlendirmek hata verirken,typeof kontrol asla olmaz.

Örneğin, IE'de XML ayrıştırmak için aşağıdakiler kullanılır:

var x = new ActiveXObject("Microsoft.XMLDOM");

Güvenli bir loadXMLyöntem olup olmadığını kontrol etmek için :

typeof x.loadXML === "undefined"; // Returns false

Diğer yandan:

x.loadXML === undefined; // Throws an error

GÜNCELLEME

typeofBahsetmeyi unuttuğum kontrolün bir diğer avantajı da, foo === undefinedkontrolün yapmadığı ve aslında aladığı bildirilmemiş değişkenlerle de çalışmasıydı ReferenceError. Bana hatırlattığı için @LinusKleen'e teşekkürler. Örneğin:

typeof someUndeclaredVariable; // "undefined"
someUndeclaredVariable === undefined; // throws a ReferenceError

Alt satır: her zaman typeofkontrolü kullanın .


10
Teşekkürler Tim. Performans hakkındaki görüşünüz mantıklı. JQuery ekibi muhtemelen dosya boyutu üzerindeki etki konusunda endişe duymaktadır. foo === undefined, simge durumuna küçültüldüğünde , muhtemelen böyle bir şeydir f===u, oysa typeof foo === "undefined"sadece azaltılabilir typeof f==="undefined".
Patrick McElhaney

1
Bunu tanımlayabilir var u = "undefined"ve azaltabilirsiniz typeof f==u, bu da işleri geliştirir, ancak yine de daha büyüktür.
Tim Down

5
İyi puan, ama typeofkayıt dışı değişkenlere karşı güvenliğinin bir avantaj olduğundan emin değilim . Herhangi bir şey varsa yazım hatalarının daha kolay geçmesini sağlar ve ne zaman gerçekte bildirilmemiş değişkenlerin türünü kontrol etmek istediğinizi göremiyorum.
David Tang

2
@ Box9: Başka bir kütüphanenin varlığını kontrol etmek için bir kütüphanede kullanmayı hayal edebiliyorum.
Tim Down

2
@jontro: JSLint'i kullanmamanın bir nedeni bu.
Tim Down

29

Typeof-varyantını kullanmanın başka bir nedeni: undefinedyeniden tanımlanabilir.

undefined = "foo";
var variable = "foo";
if (variable === undefined)
  console.log("eh, what?!");

Sonucu typeof variable yapamam.

Güncelleme : ES5'te bunun genel undefinedolarak yapılandırılamayan, yazılamayan bir özellik olduğunu unutmayın:

15.1.1 Global Nesnenin Değer Özellikleri
[...]
15.1.1.3 undefined
. Değeri undefinedundefined (bkz. 8.1). Bu özellik
{[[Yazılabilir]]: yanlış, [[Numaralandırılabilir]]: yanlış, [[Yapılandırılabilir]]: yanlış} özelliklerine sahiptir.

Ancak yine de yerel bir değişken tarafından gölgelenebilir:

(function() {
  var undefined = "foo";
  var variable = "foo";
  if (variable === undefined)
    console.log("eh, what?!");  
})()

veya parametre:

(function(undefined) {
  var variable = "foo";
  if (variable === undefined)
    console.log("eh, what?!");  
})("foo")

17
ES5'te yeniden tanımlanamaz.
Ry-

6
Global undefinedözellik ES5'te yeniden tanımlanamaz, ancak yine de yerel bir değişkenle gölgelenebilir. void 0daha kısa ve güvenlidir.
Oriol

7

Çünkü undefinedher zaman bildirilmez, ancak jQuery undefinedana işlevinde bildirir . Böylece güvenli undefineddeğeri dahili olarak kullanırlar, ancak dışarıda, typeoftarzı güvenli olmak için kullanırlar .



1

Yerel değişkenler için, localVar === undefinedyerel kapsam içinde bir yerde tanımlanmış olmaları ya da yerel olarak değerlendirilmemeleri gerektiği için kontrol etmek işe yarayacaktır.

Yerel olmayan ve hiçbir yerde tanımlanmayan değişkenler için, kontrol someVar === undefinedistisnayı atar: Yakalanmamış ReferenceError: j tanımlanmamış

Yukarıda söylediğim şeyi açıklığa kavuşturacak bazı kod. Daha fazla netlik için lütfen satır içi yorumlara dikkat edin .

function f (x) {
    if (x === undefined) console.log('x is undefined [x === undefined].');
    else console.log('x is not undefined [x === undefined.]');

    if (typeof(x) === 'undefined') console.log('x is undefined [typeof(x) === \'undefined\'].');
    else console.log('x is not undefined [typeof(x) === \'undefined\'].');

    // This will throw exception because what the hell is j? It is nowhere to be found.
    try
    {
        if (j === undefined) console.log('j is undefined [j === undefined].');
        else console.log('j is not undefined [j === undefined].');
    }
    catch(e){console.log('Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.');}

    // However this will not throw exception
    if (typeof j === 'undefined') console.log('j is undefined (typeof(x) === \'undefined\'). We can use this check even though j is nowhere to be found in our source code and it will not throw.');
    else console.log('j is not undefined [typeof(x) === \'undefined\'].');
};

Yukarıdaki kodu böyle çağırırsak:

f();

Çıktı şu olurdu:

x is undefined [x === undefined].
x is undefined [typeof(x) === 'undefined'].
Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.
j is undefined (typeof(x) === 'undefined'). We can use this check even though j is nowhere to be found in our source code and it will not throw.

Yukarıdaki kodu bu şekilde çağırırsak (aslında herhangi bir değerle):

f(null); 
f(1);

Çıktı şöyle olacaktır:

x is not undefined [x === undefined].
x is not undefined [typeof(x) === 'undefined'].
Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.
j is undefined (typeof(x) === 'undefined'). We can use this check even though j is nowhere to be found in our source code and it will not throw.

Bunu şu şekilde yaptığınızda: typeof x === 'undefined'temelde şunu soruyorsunuz: Lütfen değişkenin xkaynak kodda bir yerde olup olmadığını (tanımlanmışsa) kontrol edin . (Az çok). C # veya Java biliyorsanız, bu tür bir denetim hiçbir zaman yapılmaz, çünkü yoksa, derlenmez.

<== Fiddle Me ==>


1

Özet:

Global kapsamda, değişken bildirilmediyse veya değere sahipse aslında true değerini döndürmek istiyoruz undefined:

var globalVar1;

// This variable is declared, but not defined and thus has the value undefined
console.log(globalVar1 === undefined);

// This variable is not declared and thus will throw a referenceError
console.log(globalVar2 === undefined);

Global kapsamda, bir değişkenin bildirildiğinden% 100 emin değiliz, bu bize bir referenceError verebilir. Kullandığımız zaman typeofbilinmeyen değişkeni operatörü biz değişken bildirilmedi bu konuyu almıyorsanız:

var globalVar1;

console.log(typeof globalVar1 === 'undefined');
console.log(typeof globalVar2 === 'undefined');

Bunun nedeni , bir değişken bildirilmediğinde veya şu anda tam olarak istediğimiz değeri tutan typeofoperatörün dizeyi döndürmesidir .undefinedundefined


  • Yerel değişkenlerde bu sorun yoktur, çünkü önceden bu değişkenin var olacağını biliyoruz. Değişken mevcutsa ilgili işleve bakabiliriz.
  • Nesne özelliklerinde bu sorun yoktur, çünkü var olmayan bir nesne özelliğini aramaya çalıştığımızda değeri de alırız. undefined

var obj = {};

console.log(obj.myProp === undefined);


-5

typeof a === 'undefined'a === 'undefined'v6.9.1 düğümünde yaklaşık 2 kat daha hızlıdır .


3
Bunlar yazdığınız şeyler değil. Sanırım undefinedikinci bölümde demek 'undefined'
istedin
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.