JavaScript'te neden "boş" değer var?


116

JavaScript'te, temelde 'Ben yokum' yazan iki değer vardır - undefinedve null.

Bir programcı herhangi bir numara olabilir atanmamış olan A özellik undefinedolmak için bir özellik için, ama sırayla null, nullaçıkça kendisine atanmalıdır.

Bir keresinde buna ihtiyaç olduğunu düşünmüştüm nullçünkü undefinedilkel bir değer ve nullbir nesnedir. Hatta eğer değil typeof nullverecektir 'object'- vasıtalar, Aslında, her ikisi de ilkel değerler şunlardır: undefinedveya nullher ikisi de boş nesne dönüştürülebilir gibi (bir kurucu içinde, açığa başarısızlığa bir hata oluşturması sahiptir), bir yapıcı işlevi döndürülebilir.

Ayrıca ikisi de falseboole bağlamlarında değerlendirir . Aklıma gelen tek gerçek fark, birinin sayısal bağlamlarda NaN, diğerinin değerlendirmesidir 0.

Öyleyse neden her ikisi de var undefinedve nullbu, nullbir özelliğin ayarlanıp ayarlanmadığını bulmaya çalışırken yanlış bir şekilde kontrol eden programcıların kafasını karıştırıyorsa ?

Bilmek istediğim şey, kullanılması gereken ve bunun yerine nullkullanılarak ifade edilemeyen makul bir örneğe sahip olup olmadığıdır undefined.

Dolayısıyla, genel fikir birliği undefined, 'böyle bir mülkiyet yok' nullanlamına gelirken , 'mülk var, ancak değeri yok' anlamına geliyor gibi görünüyor .

JavaScript uygulamaları bu davranışı gerçekten zorlasaydı undefined, ancak tamamen geçerli bir ilkel değer olsaydı, bununla yaşayabilirim, bu nedenle bu sözleşmeyi bozmak için mevcut mülklere kolayca atanabilir. Bu nedenle, bir özelliğin var olduğundan emin olmak istiyorsanız, inoperatörü veya hasOwnProperty()yine de kullanmanız gerekir . Yani bir kez daha: için ayrı değerler için pratik kullanım nedir undefinedve null?

Aslında undefinedartık kullanımda olmayan ancak istemediğim özelliklerin değerlerini geri almak istediğimde kullanıyorum delete. Onun nullyerine kullanmalı mıyım ?


3
Son sorunuzu cevaplamak için: Hayır, özellikleri ayarlamamalısınız undefined.
Shog9

4
"tanımsız", genel kapsamdaki "tanımsız" ilkel değerine sahip bir değişkendir. Değişken için başka bir değer tanımlamak mümkündür: {undefined = "Merhaba"; alert (tanımsız);} için teste daha güvenilir yolu tanımsız: {(typeof myvar === "tanımsız") alert ( "tanımsız")} eğer
Bazı

1
Bölüm 4.3.9 bakın - 12 bu ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf küresel kapsamda "tanımsız" değişkeni için tanımsız / null ve 15.1.1.3.
bazı

1
Ya bir nesneyi silmelisiniz ya da bu daha mantıklıysa onu null olarak ayarlamalısınız, ancak tanımsız olarak değil.
bazı

4
In JavaScript, there are two values which basically say 'I don't exist' - undefined and null.Hayır, sadece bunu undefinedsöylüyor.
Orbit'te Hafiflik Yarışları

Yanıtlar:


78

Soru gerçekten "JS'de neden boş bir değer var?" Değildir - çoğu dilde bir tür boş değer vardır ve genellikle çok yararlı kabul edilir.

Soru, " JS'de neden tanımlanmamış bir değer var ". Kullanıldığı başlıca yerler:

  1. ilan ettiğinizde var x;ancak ona atamadığınızda x, tanımsız tutar;
  2. işleviniz bildirdiğinden daha az argüman aldığında;
  3. var olmayan bir nesne özelliğine eriştiğinizde.

null(1) ve (2) * için de kesinlikle işe yarardı. (3) gerçekten bir istisnayı hemen atmalı ve undefineddaha sonra başarısız olacak bu tuhaflığı geri döndürmek yerine , hata ayıklama zorluğunun büyük bir kaynağıdır.

*: (2) 'nin bir istisna atması gerektiğini de iddia edebilirsiniz, ancak o zaman varsayılan / değişken argümanları için daha iyi, daha açık bir mekanizma sağlamanız gerekir.

Bununla birlikte, JavaScript'in başlangıçta istisnaları yoktu veya bir nesneye belirli bir isim altında bir üyesi olup olmadığını sormanın herhangi bir yolu yoktu - tek yol (ve bazen hala) üyeye erişmek ve ne aldığınızı görmektir. Bunun nullzaten bir amacı olduğu ve ona bir üye atamak isteyebileceğiniz düşünüldüğünde, farklı bir bant dışı değer gerekiyordu. Yani undefined, sizin de belirttiğiniz gibi sorunlu ve asla kurtulamayacağımız başka bir harika JavaScript 'özelliği' var.

Artık kullanımda olmayan ancak silmek istemediğim özelliklerin değerlerini geri almak istediğimde aslında undefined kullanıyorum. Bunun yerine null kullanmalı mıyım?

Evet. undefinedDiğer diller bunun yerine bir istisna oluşturduğunda sinyal vermek için özel bir değer olarak tutun .

nullbir şeyi ayarlamanın nullsize hata verebileceği bazı IE DOM arayüzleri dışında genellikle daha iyidir . Çoğunlukla bu durumda boş dizgeye ayarlamak işe yarayacaktır.


10
Args genişletilebilir. İstediğiniz kadar girebilirsiniz ve bir işlev potansiyel olarak yinelenebilir ve hepsini kullanabilir. Nesnelere herhangi bir zamanda yeni bir özellik atanabilir. Bunların her ikisi de güçlü özellikler, ancak tercih ettiğiniz gibi atılan istisnalara sahip olmanın çok fazla ek yük olacağını düşünüyorum. IMO, değiş tokuş etmeye değer. JS'de var olup olmadığını kontrol etmek için genellikle daha katı dil paradigmalarında döküm yaptığımdan çok daha az zaman harcıyorum.
Erik Reppen

Bir soruya verilen kabul edilen cevabın "bu gerçekten soru değil ..." ile başlaması komik.
Phillip

@bobince JS'nin ilk sürümlerinde inoperatöre sahip değil hasOwnPropertymiydi? Çünkü obj.hello !== undefinedbir nesnede bir özelliğin var olup olmadığını kontrol etmekten çok daha güvenlidirler .
Andy

Boşver, kendi sorumu cevapladım. MDN'ye göre ikisi de ES3'te tanıtıldı.
Andy

37

En iyi burada açıklanmıştır , ancak özet olarak:

tanımsız, bir tür ve değerin olmaması ve null, bir değerin olmamasıdır.

Dahası, basit '==' karşılaştırmaları yapıyorsanız, haklısınız, ikisi de aynı çıkıyor. Ama hem türü hem de değeri karşılaştıran === deneyin ve farkı göreceksiniz.


1
Bunu biliyorum null !== undefined- benim sorum neden aynı anlamsal kavramı ifade eden iki şeye ihtiyaç olduğuydu; ayrıca, bağlantınız 'boş bir nesne' olduğundan bahsediyor - bu yanlış, bu ilkel ...
Christoph

2
Aynı anlamsal kavram değiller. En azından bana göre, boş değer atanan bir özellik ile mevcut olmayan bir özellik arasında önemli bir fark var.
Daniel Schaffer

Ama hepsi bu, aynı anlamsal kavram değiller. Null, == kullanıldığında programcıya kolaylık sağlamak için aynı şeyi ima etmeye zorlanır.
Eddie Parker

1
@EricElliott: typeofyalanlar - spec okumak veya dönen deneyin nullbir yapıcı gelen
Christoph

5
@EricElliott: kurucuların dönüş değerinin yanlışlık ile ilgisi yoktur, ancak nesne-lik ile ilgisi yoktur: eğer dönüş değeri bir nesne ise, bunu döndür; nullveya gibi bir 42ilkelse, dönüş değerini atın ve bunun yerine yeni oluşturulan nesneyi geri döndürün
Christoph

17

Her ikisine de sahip olmak için herhangi bir neden olduğunu sanmıyorum nullve undefinedçünkü birçok insanın önerdiği tek neden (" undefinedböyle bir değişken / özellik olmadığı anlamına gelir") en azından JavaScript'te geçerli değil. undefineddeğişkenin / özelliğin var olup olmadığını söyleyemem.

console.log(foo);               // "ReferenceError: foo is not defined"
                                // foo does not exist
var foo;
console.log(foo);               // "undefined", a different response
console.log(foo === undefined); // "true", but it does exist

var obj = {};
console.log(obj.hasOwnProperty("foo")); // "false", no such property
obj.foo = undefined;
console.log(obj.hasOwnProperty("foo")); // "true", it exists and has the value "undefined"
console.log(obj.foo === undefined);     // "true", but it does exist

obj.bar = "delete me";
obj.bar = undefined;
console.log(obj.hasOwnProperty("bar")); // "true", not actually deleted
delete obj.bar;
console.log(obj.hasOwnProperty("bar")); // "false", deleted

Gördüğünüz gibi, kontrol etmek foo === undefinedsize foovar olup olmadığını söylemez ve ayar obj.bar = undefinedaslında silinmez bar.

undefined"Varolmayışı" temsil etmesi gereken JavaScript yazarının orijinal amacı olabilir . Ancak uygulama böyle olmadı.


1
Yukarıdaki kod örneklerinizde undefinedile değiştirin nullve yanıtların tümü aynıdır. Bunun soruyu nasıl yanıtladığından emin değilim. Bu, başka birinin cevabına bir yorum olarak mı ifade edildi?
Eric Elliott

1
Sorusuna @EricElliott Benim cevabı ikisine birden sahip sebep yok olmasıdır nullve undefinedbirçok kişi önerilen tek nedeni geçerli olmadığından,.
Lei Zhao

Cevabınızı düzenlemeli ve bunu gerçekten söylemelisiniz. Cevabı vermiş olsaydın, oy verebilirdim. =)
Eric Elliott

@EricElliott Bence haklısın. Cevabımı düzenledim. Teşekkürler!
Lei Zhao

3
Bu örnek aslında bir değişken atamadıysanız geri döndüğünü gösterir undefined. Ama undefinedona atadıysanız , aslında değil undefined- onunla tanımlanmıştır undefinedve ona atıfta bulunmaktadır. Arasındaki tek fark, undefinedve nullonların kullanımı ve tarihsel amacıdır. İkisi de atomik.
Aleksej Komarov

6

Her ikisine de ihtiyaç duymak tamamen mümkündür. Örneğin, WMI'yi sorgularsanız, boş değere sahip bir sınıf döndürme özelliklerine sahip olmak tamamen mümkündür. Tanımlanmışlardır, sadece o anda boş kalırlar.


6

JavaScript'in undefined"böyle bir özellik yoktur" ve null"mülkün değeri yoktur" şeklindeki sonucunuzun tamamen doğru olduğunu düşünüyorum. Ve JavaScript kadar dinamik bir dilde çok önemli bir ayrımdır. Ördek yazmanın kullanılması, var olmayan ve bir değere sahip olmayan bir özelliği ayırt edebilmemiz gerektiği anlamına gelir. Tür bilgilerini elde etmenin birincil yoludur. statik olarak yazılmış bir dilde, bir alanın boş olması ile mevcut olmayan bir alan arasında kesin bir ayrım vardır. JavaScript'te bu farklı değil. Ancak çalışma zamanında kontrol edilir ve o zamana kadar değiştirilebilir.

Çoğu zaman ayrım bulanık olduğu için uygulamanın tuhaf olduğunu kabul etmek zorundayım. Bununla birlikte, JavaScript'te ayrımın önemli olduğunu düşünüyorum. Ve atama yapabilmek undefinedesastır.

Bir süre önce JavaScript ile yazılmış bir çevrimiçi RPG hakkında bir blog yazısı okuduğumu hatırlıyorum. Nesnelerin prototipler (sınıflar, işlevler, her neyse) yerine mevcut örneklerin kopyaları olarak oluşturulduğu ve daha sonra değiştirildiği örnekler kullandı. Bu gerçekten undefinedvar olan nesneleri değiştirirken bunun ne kadar güçlü olabileceğini anlamamı sağladı , ancak onu kimin yazdığını hatırlayamıyorum.


Lütfen bu RPG'yi paylaşır mısınız?
Michael

3

Anlamsal olarak farklı şeyler ifade ederler. Null türünün etki alanında tam olarak bir değeri vardır, null ve bu özel değere bir özellik atanabilir. Tanımsız, atanmış herhangi bir değerin belirgin bir eksikliğini gösterir.


1
ancak undefinedmülklere atamak için sadece ince kullanabilirsiniz , bu nedenle bu sözleşme (yalnızca undfinedböyle bir mülk yoksa iade edilir) programcı tarafından kolayca ihlal edilebilir ...
Christoph

2
Sen can , ama kesinlikle olmamalı. Tanımsız, JavaScript'te çok temel / basit bir istisna biçimi olarak kullanılır - bunu bir değer olarak kullanmayın ve bir özelliğe atamayın! Bu çılgın adam.
rfunduk

3

Bir Java programcısı olarak, undefined ve null arasında büyük bir fark görüyorum. JavaScript kodlama, o kadar değil, çünkü JavaScript güçlü bir şekilde yazılmamıştır ve tanımsız ve boş arasındaki farklar, çalışma zamanı tarafından sıklıkla gerçekleştirilen otomatik dönüştürmeler tarafından bulanıklaştırılır. BTW, bu dönüşümlerden sık sık yararlanıyorum; JS kodumu daha kompakt ve okunabilir hale getiriyorlar.

Sorunuzu yanıtlamak için, tanımsız, bir değerin asla ayarlanmadığı anlamına gelir. Pratik olarak konuşursak, bu genellikle bir hataya işaret eder. YourObject.property undefined ise, bu, özelliği herhangi bir nedenle ayarlamadığınız veya hiç var olmayan bir şey arıyorum demektir. Birden fazla kodlayıcı ile bir proje üzerinde çalışırken bu gerçek bir sorundur.

null, "değer yok" ifadesinin açıkça ayarlandığı anlamına gelir. Pratik olarak konuşursak, bana mülk hakkında, belki de bu bağlamda kullanılmadığını veya henüz bir değerin belirlenmediğini söylüyorsunuz.

Java'da, tanımlanmamış bir alana erişme girişimleri her zaman bir istisnayla sonuçlanır. Aslında, derleyicinin kodunuzda sizi bu konuda uyarması sağlanabilir.


0

Bu örneği deneyin:

<html>
<head>
    <script type="text/javascript">
        function ShowObjProperties(obj) {
            var property, propCollection = "";

            for(property in obj) {
                propCollection += (property + ": " + obj[property] + "\n");
            }

            alert(propCollection);
        }

        var obj = {
            userid: 3,
            name: 'me!',
            speak: function() { alert('Hi! My name is ' + this.name + ' and my ID is ' + this.userid + '.'); }
        }

        //Shows all properties
        ShowObjProperties(obj);

        //The Speak function is no longer in the list!
        delete obj.speak;
        alert(typeof obj.speak);
        ShowObjProperties(obj);

        //The UserID is still listed, it just has no value!
        obj.userid = null;
        ShowObjProperties(obj);
    </script>
</head>
<body>

</body>
</html>

Burada 2 farklı tip için çok gerçek bir kullanım olduğunu düşünüyorum.


Ve prototiplerde bence bir üye boş veya sadece tanımsız.
Kev

ancak bu yalnızca kimse onu kırmaya çalışmadığı sürece işe yarar - ayarlarsam obj.userid = undefinedbaşarısız olur - sorumun son düzenlemesine bakın
Christoph

0

Sonuç olarak javascripts dinamik doğası var.

Şeyler daha sonra eklenebilmeleri için tanımlanmamış olabilir. Muhtemelen javascript'in bu kadar güçlü ve genişletilebilir olmasının nedeni budur.


ve bu sorumla ne şekilde alakalı?
Christoph

2
Alakalı çünkü sorunuzu cevaplıyor. 'boş', 'değeri yoktur' anlamına gelen 'tekil' türdür. 'tanımsız' size bir şeyin şok edici olduğunu söylüyor, biliyorum ... tanımlanmamış. Tamamen farklı şeyler.
rfunduk

0

Programınızı javascript'in olaylı paradigması etrafına sararsanız, bu önemli bir dil özelliğidir.

// a key exists as a placeholder for something
if(obj[name] === null) 
// no key exists int eh hashtable that is in this object
if(obj[name] === undefined)

Varsayılan eylemi belirtmek için 'hiçbir şey' kullanmaktan farklı bir eylemi belirtmek için 'hiçbir şey'i temsil edecek bir değere ihtiyaç duyan bir veri kümesiyle uğraşıyorsanız bu çok kullanışlıdır.

filter_func_pt = {
  date:function(d){ return Math.round(d.getTime()/1000);},
  user: null,
}

function transform(obj){
    var ret = {};
    for( var prop in obj){
       var f = filter_func_pt[prop];
       if(f)
          ret[prop] = f(obj);
       else if(filter_func_pt[prop] === null)
         continue;
       else
         ret[prop] == obj;
    }
  return ret;
}

var a = {
   date: new Date(),
   user: 'sam'
   votes: [23, 41, 55] 
};

var b = transform(a);

/* b = {
 *    date: 1298582417
 *    votes: [23, 41, 55]
 * }
 */

Yukarıdaki kodda null anahtar kelime ve tanımsız sunucu çok açık ve farklı amaçlar. tanımsız döndüren filter_func_pt nesnesinde bulunmayan arama , özelliği dönüş nesnesine olduğu gibi eklemek için araçlar, boş bir değer ise değerin saklanması ve eklenmemesi gerektiğini ve bunda herhangi bir gerçek değerin varlığını belirtir. case, değeri ret nesnesine eklemeden önce dönüştürmek için kullanılan bir işlevi temsil eder .


Bu örnek uydurma ve biraz saçma. Null, niyetinizi hiç netleştirmez - aksine onu maskeler. Anlamı açıklığa kavuşturmak için daha açık bir dizge kullanabilirdin. Örneğin, 'durdurun' veya 'soyun' ve daha sonra işlev türü hakkında daha net bilgi alabilir ve aslında bir işlevin varlığını kontrol edebilirsiniz.
Eric Elliott

0

boş güzeldir

diğer tüm Canlı Komut Dosyası Türleri gibi.

cite: JavaScript'te temelde 'Ben yokum' diyen iki değer vardır - tanımsız ve boş.

Neden yanlış şeyler söylemek istersiniz ?!

"boş" olduğunu "boş Nesne" sadece "0" bir olduğu gibi "boş Numara" . 0, hiçbir şey değildir - ancak bir Sayı Türü olarak var olur. null elbette boştur ama "öyle" ve bir Nesne Türü için iyi tanımlanmış bir şey .

Bu şeylerden, olmadıkları zaman "tipler" olarak bahsetmek yaygındır. Aslında bunlar "kategoriler" dir. Ama artık bitti.

Bu nedenle, "boş" un bir Türü olmayan bir Nesne Türü olduğunu söylemeye devam edeceğiz. Ve "boş" der ki "Ben çok varım [!], Ama benim türümden içeriğim yok".

Oysa tanımsız , hem Tür hem de Tür'den yoksundur; burada tanımsız , aynı zamanda Tür tanımıdır. Tanımlanmamış bir tür türü, onun ayırt edici tipolojisi haline gelir. Bir tür ["hiçbir şey" yoktur ve "hiçbir şey" i nasıl tanımlarsınız?] Sorusu.

cite: undefined veya null, her ikisi de boş bir nesneye dönüştürücü olacağından, bir yapıcı işlevinden döndürülebilir

Bir kez daha yanlış bir şey söylemeyi başardın. Tabii ki hayır, "tanımlanmamış" bir Nesne değil, biz insanların anladığı basit bir Token; ama bu boşluğun aksine - ve size şunu söylüyor: Türü doğru, ama aradığınız Tür onun içinde yok veya en azından şu anda değil. Daha sonra, içine bir nesne \ atadığımızda bizi ziyaret edin.

cite: Aklıma gelen tek gerçek fark, birinin NaN, diğerinin sayısal bağlamlarda 0 olarak değerlendirilmesidir.

Bu, belirtildiği gibi temel ayrımının tüm noktasını yapar: tanımsız , basit bir belirteçtir ve uzak akrabalarıyla aynı 'genetik' materyalden oluştuğu için: dizeler, [+ tanımsız] işlem onu ​​baş aşağı çevirecektir. NaN, benzer şekilde null, tabii ki kendisini doğru bir 0 \ Number türüne dönüştürecektir ve tanımsız olanın aksine, bu bir dizgeye dönüşecektir (! Boş değildir!) Ve bu yüzden bunun yerine NaN verir . Nerede: + undefined >> + "undefined" >> NaN. Sayısal bağlam açık bir değer beklediğinden.

Boole bağlamı referans beklerken - dönüştürülecek hiçbir şey bulmaz ve 'false' verir.

Şimdi keselim ...

cite: O halde bir kez daha: undefined ve null için ayrı değerler için pratik kullanım nedir?

Size sadece iki ampirik örnek vermeye çalışacağım ve yeterli olmasını umacağım

oElement.onclick >> null

// -özellik var demektir; beklenen değeri Type: Object ve bu oElement "onclick" olayını destekliyor!

oElement.innerText >> ""

// anlamına gelir - özellik var; beklenen değeri Type: String'dir , bu, oElement'in "innerText" özelliğini desteklediği anlamına gelir.

her iki durumda da - "tanımsız" mesajı alırsanız bu, mülkün mevcut olmadığı anlamına gelir; desteklenmiyor veya yanlış (ua satıcı) bir uygulamaya sahip.

Donmaya devam edin ve eğlenin.


Gönderilerinize zarar verme, aeneas. Katkınızı kaldırmak istiyorsanız bunları silin ( bu yorumun hemen üzerindeki Sil düğmesini kullanarak ).
Michael Petrotta

silme düğmesi yoktur - ancak görürseniz, lütfen tıklayın!

0

undefined ve null ile ilgili harika tartışmaları okuduktan sonra, google'daki küçük arama beni Mozilla Belgelerine götürdü https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null bundan bahsediliyor - genellikle boş bir nesnenin beklenebileceği ancak hiçbir nesnenin ilgili olmadığı bir yerde geri alınır.

Boş nesne desenine benzer değil https://en.wikipedia.org/wiki/Null_object_pattern

Sanırım bu Null veri türüne sahip olmak mantıklı.

Belgelerde ayrıca typeof null // "nesne" olarak bahsedilir (eski nedenlerden dolayı "boş" değil)

Eski nedenlerin ne olduğundan emin değilim

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.