JavaScript'te tanımsız yerine null kullanmanın nedeni nedir?


103

Uzun zamandır JavaScript yazıyorum ve kullanmak için hiç bir nedenim olmadı null. Görünüşe göre undefinedbu her zaman tercih edilir ve programlı olarak aynı amaca hizmet eder. Bunun nullyerine kullanmak için bazı pratik nedenler nelerdir undefined?



Bunun gibi document.getElementById()geri dönebilen nullama dönmeyen yöntemler var, undefinedbu durumda neden geri dönüşü test edesiniz undefined? (Elbette, ==yerine kullanırsanız işe yarar ===, ama yine de, neden kasıtlı olarak yanlış şeyi test edersiniz?)
nnnnnn

Öngörülebilir türlere sahip olmak yardımcı olabilir ve bu, birini veya diğerini kullanmayı düşünmeye rehberlik edebilir. Bir nesnenin her zaman geri döndüğü, ihtiyaç duyulduğu veya tasarım gereği istendiği durumlarda, yanlış sonuçlar için boş kullanın (örn. document.getElementById('does-not-exist')). Değişkenler var a;ve işlev dönüş değerleri varsayılan olarak tanımsızdır. Geçmişte null global kapsamdaydı, bu yüzden onu kullanmak yürütmeyi yavaşlattı ve beni diğer sahte türleri (false, '', 0) serbest referanslara tercih etmeye yöneltti. Ben şahsen, başka türlü zorlayıcı bir sebep olmadıkça boşluğa kaçınırım çünkü bunun daha basit olduğunu düşünürüm, ki bu genellikle daha iyidir.
jimmont

Yanıtlar:


60

Null ve undefined, aslında aynı anlama gelen iki farklı değerdir. Tek fark ise sözleşmeler sen bunları kullanmak nasıl senin sisteme. Bazılarının bahsettiği gibi, bazı insanlar "nesne yok" anlamında null kullanır; burada bazen tanımsız bir nesne elde edebileceğiniz, hiçbir nesnenin beklenmediği (veya bir hata olduğu) anlamına gelir. Bununla ilgili sorunum tamamen keyfi ve tamamen gereksiz.

Bununla birlikte, büyük bir fark vardır - başlatılmayan değişkenler (diğer şeylerin yanı sıra hiçbir bağımsız değişkenin iletilmediği işlev parametreleri dahil) her zaman tanımsızdır.

Bu yüzden kodumda, kontrol etmediğim bir şey null döndürmediği sürece asla null kullanmam (örneğin regex eşleşmesi). Bunun güzelliği, her şeyi çok fazla benzetmesidir. X === tanımsız olup olmadığını kontrol etmek zorunda değilim || x === boş. Ve == kullanma alışkanlığınız varsa veya basitçe if (x) ... gibi şeyler. Yapma. !x0, null, NaN gibi boş bir dizge için doğru olarak değerlendirilecektir - yani muhtemelen istemediğiniz şeyler. Korkunç olmayan bir javascript yazmak istiyorsanız, her zaman üçlü eşittir === kullanın ve asla null kullanmayın (bunun yerine tanımsız kullanın). Hayatınızı kolaylaştıracak.


138
Ben buna katılmıyorum. Null, programlı olarak boş bir şeyi tanımlamak için kullanılır. Tanımsız, referansın mevcut olmadığını ifade eder. Boş değerin "hiçbir şey" için tanımlanmış bir referansı vardır. Bir nesnenin mevcut olmayan bir özelliğini çağırıyorsanız, o zaman tanımsız olursunuz. Bu mülkü kasıtlı olarak boş yaparsam, o zaman boş olmalıdır ki bilerek olduğunu bilirsiniz. Çoğu javascript kitaplığı bu şekilde çalışır.
com2ghz

6
@ com2ghz Tarif ettiğiniz şey birçok felsefeden biridir. Pek çok js kitaplığı gerçekten bu şekilde çalışır. Birçoğu da bu şekilde çalışmıyor. Javascript'te, null ile yapabildiğiniz gibi bir nesnede veya dizide açık tanımsız bir değeri kolayca depolayabilirsiniz. Her ikisinin de anlamları tamamen ve tamamen içeriğe bağlıdır. Yani, onların ne demek istediğini kastediyorlar.
BT

3
JS'nin korkunç bir dil olmasının nedeni budur. Sizin de dediğiniz gibi, birçok kütüphanenin kendi felsefesi var ama siz 1 proje için birçok kütüphaneyi dahil ediyorsunuz. Yani bu kütüphanelerin birçok geleneğiyle karşılaşıyorsunuz. Kaç kez farklı yanlış kontroller yapmanız gerekiyor? Boş bir nesneyi bir dizgeye son olarak birleştirip dizge olarak "boş" elde ettiğiniz son sefer olmayacaktır. Ya da sayısal değer olarak 0'ı geçmek ve IF ifadesinin neden t'yi yanlış olarak işlediğini merak etmek.
com2ghz

2
@ com2ghz Yani JS korkunç bir dil çünkü hem null hem de undefined var mı? Tüm ana dillerde düzinelerce kötü dil kararını sayabilirim, js istisna değildir. Kelimenin tam anlamıyla hiçbir zaman kodumda yanlış kontrollere ihtiyacım olmuyor veya kullanmak istemiyorum ve her zaman ===veya !==. JS, nasıl kullanılacağını biliyorsanız, fevkalade ifade edici bir dildir.
BT

6
Sağ. Az önce null/ undefinedikilisinin gerekli olduğunu öğrendim çünkü JS'nin ilk sürümü hasOwnPropertyveya inoperatörü yoktu . Şimdi öyle, ES6'da veya gördüğüm herhangi bir ES7 teklifinde bunlardan birinin neden kaldırılmadığını gerçekten anlamıyorum.
Andy

86

Gerçekten bir cevap var, ama göre yok Nicholas C. Zakas , kitabının sayfa 30 " Web Geliştiriciler için Profesyonel JavaScript " :

Daha sonra bir nesneyi tutması amaçlanan bir değişkeni tanımlarken, değişkeni nullbaşka herhangi bir şeyin aksine olarak başlatmanız önerilir . Bu şekilde, nulldeğişkenin daha sonra bir nesne referansı ile doldurulup doldurulmadığını belirlemek için değeri açıkça kontrol edebilirsiniz.


8
+1 evet, katılıyorum ve her zaman vars'ı null olarak başlatmayı hatırlamaya çalışıyorum. O zaman (oldukça) eminim ki undefinedbu bir felaket oldu demektir Sadece imho.
Pete Wilson

9
@Pete - ama size "felaket" hakkında hiçbir şey söylemiyor, peki ne anlamı var? Ve bu varsayımı yalnızca işlevin kuralı izlediğini biliyorsanız yapabilirsiniz.
RobG

7
Öte yandan, değişkeni ile başlatabilir var myVar;ve undefineddaha sonra bir nesne referansı ile doldurulup doldurulmadığını belirlemek için değeri açıkça kontrol edebilirsiniz . Demek istediğim, bu tamamen akademik - her iki şekilde de yapabilirsiniz ve bir şekilde diğerine tavsiyede bulunan herkes kendi kurallarını zorluyor.
thdoan

1
Sahip olduğum tek sorun (15 yıl önce JavaScript ile başladığımdan beri) çok sık test etmek zorunda kalmanız undefinedve null. Bu hala gerçekten can sıkıcı. nullEkstra nulltest sayısını azaltmak için bir değişken atamaktan kaçınıyorum .
G Man

4
@GMan - ==Karşılaştırmanın (aksine ===) mantıklı olduğu tek yer burasıdır : v == null(veya v == undefined) null veya undefined olup olmadığını kontrol eder.
Rick Love

15

Günün sonunda, hem çünkü nullve undefinedaynı değere zorlamak ( Boolean(undefined) === false && Boolean(null) === false), teknik olarak işin yapılması için birini kullanabilirsiniz. Ancak, doğru yol var, IMO.

  1. Kullanımını undefinedJavaScript derleyicisine bırakın .

    undefinedbir referansa işaret etmeyen değişkenleri tanımlamak için kullanılır. JS derleyicisinin sizin için ilgileneceği bir şey. Derleme zamanında, JS motoru yükseltilmiş tüm değişkenlerin değerini olarak ayarlayacaktır undefined. Motor kodda ilerlerken ve değerler kullanılabilir hale geldiğinde, motor ilgili değerleri ilgili değişkenlere atayacaktır. Değer bulamadığı değişkenler için, değişkenler ilkele bir referans sağlamaya devam edeceklerdir undefined.

  2. Yalnızca bir değişkenin değerini "değer içermeyen" olarak açıkça belirtmek istiyorsanız null kullanın.

    @ Com2gz'nin belirttiği gibi: nullprogramatik olarak boş bir şeyi tanımlamak için kullanılır. undefinedreferansın mevcut olmadığını söylemek anlamına gelir. Bir nulldeğerin "hiçbir şey" için tanımlanmış bir referansı vardır. Bir nesnenin mevcut olmayan bir özelliğini çağırıyorsanız, o zaman elde edersiniz undefined. Bu mülkü kasıtlı olarak boşaltacaksam, o zaman bilerek nullolduğunu bilmeniz için olmalıdır .

TLDR; undefinedİlkel olanı kullanmayın . Bu, değişkenleri atamadan bildirdiğinizde veya referansı olmayan nesnelerin özelliklerine erişmeye çalıştığınızda JS derleyicisinin sizin için otomatik olarak ayarlayacağı bir değerdir. Öte yandan, nullyalnızca ve ancak kasıtlı olarak bir değişkenin "değeri olmamasını" istiyorsanız kullanın.

Hiçbir zaman hiçbir şeyi açıkça tanımlanmamış olarak ayarlamadım (ve etkileşim kurduğum birçok kod tabanında buna rastlamadım). Ayrıca nadiren kullanıyorum null. Kullandığım tek zaman null, bir argümanın değerini bir işleve değersiz olarak belirtmek istediğim zamandır, yani:

function printArguments(a,b) {
  console.log(a,b);
}

printArguments(null, " hello") // logs: null hello

Bu seçilen cevap
olmalıydı

13

tanımsız şey kavramının olmadığı yerdir; türü yoktur ve bu kapsamda daha önce hiç başvurulmamıştır; null, var olduğu bilinen şeydir, ancak değeri yoktur.


4
Bir değer atama girişiminde bulunulduğunu, ancak başarısız olduğunu ve bunun yerine tanımsız olarak atandığını nasıl anlarsınız ?
RobG

11

Herkesin kendi kodlama yöntemi ve kendi iç semantikleri vardır, ancak yıllar içinde bunu, bu soruyu soran insanlara verdiğim en sezgisel tavsiye olarak buldum: şüphe duyduğunuzda JavaScript'in yaptığını yapın .

Diyelim ki bir jQuery eklentisi için seçenekler gibi nesne özellikleriyle çalışıyorsunuz ... kendinize JavaScript'in henüz tanımlanmamış bir özelliğe ne kadar değer verdiğini sorun - cevabı undefined. Bu bağlamda, JavaScript ile tutarlı olması için bu tür şeyleri 'tanımsız' ile başlatırım (değişkenler için var myVar;bunun yerine yapabilirsiniz var myVar = undefined;).

Şimdi, DOM manipülasyonu yaptığınızı varsayalım ... JavaScript, var olmayan öğelere hangi değeri atar? Cevap şudur null. Bu, daha sonra DOM ile ilgili bir öğeye, belge parçasına veya benzerine bir referans tutacak bir yer tutucu değişken oluşturuyorsanız, başlatacağım değerdir.

JSON ile çalışıyorsanız, özel bir durum yapılmalıdır: tanımsız özellik değerleri için, bunları ya ayarlamalısınız ya ""da nullbir değeri undefineduygun JSON biçimi olarak kabul edilmediğinden.

Bununla birlikte, önceki bir posterin ifade ettiği gibi, bir mavi ayda bir nullveya undefinedbirden fazla şeyi başlattığınızı fark ederseniz , belki de uygulamanızı nasıl kodlayacağınızı yeniden düşünmelisiniz.


Bu iyi bir duruş olsa da, şu yanıtı eklemek isterim: stackoverflow.com/a/37980662/883303
Frederik Krautwald

@FrederikKrautwald bağlantı için teşekkürler - bu çok net bir açıklama.
thdoan

10

Burada önerilen sözleşmeyi benimseyebilirsiniz, ancak bunun için gerçekten iyi bir neden yok. Anlamlı olacak kadar tutarlı bir şekilde kullanılmaz.

Kuralı yararlı kılmak için, önce çağrılan işlevin kuralı izlediğini bilmelisiniz. Ardından, döndürülen değeri açıkça test etmeniz ve ne yapacağınıza karar vermeniz gerekir. Eğer alırsanız tanımsız , hatanın çeşit meydana varsayabiliriz denilen fonksiyon bildiğini . Ancak bir hata olduysa ve işlev bunu biliyorsa ve bunu daha geniş bir ortama göndermek yararlıysa, neden bir hata nesnesi kullanmayalım? yani bir hata mı atmak?

Yani günün sonunda, basit ortamlarda çok küçük programlar dışında hiçbir şey için sözleşme pratik olarak yararsızdır.


3

Null içindeki , tanımsız olan yararlı bir özellik şu nitelikleri karşılamaz:

> null + 3
3
> undefined + 3
NaN

Kullandığım nullBen sayısal bir değer 'kapatmak' için ya da bazı başlatmak istediğinizde. Son kullanımım css dönüşümünü manipüle etmekti:

const transforms = { perspective : null, rotateX : null };
// if already set, increase, if not, set to x
runTimeFunction((x) => { trasforms.perspective += x; });
// still useful, as setting perspective to 0 is different than turning it off
runTimeFunction2((x) => { transforms.perspective = null; });

// toCss will check for 'null' values and not set then at all
runTimeFunction3(() => { el.style.transform = toCss(transforms); });

Ben emin değil misiniz gerektiğini bu özellik düşünceyi kullanmak ...


2

DOM düğümleri ve öğeleri tanımsız değildir, ancak boş olabilir.

  • Bir elemanın son alt öğesinin nextSibling değeri null.

  • İlk çocuğun previousSibling öğesi null.

  • Öğe belgede yoksa, document.getElementById başvurusu boştur.

Ancak bu durumların hiçbirinde değer tanımsız değildir ; orada sadece düğüm yok.


Açıklama için teşekkürler. Benim için bu daha mantıklı olamaz.
tomekwi

Gerçekten neyi kontrol etmeye çalıştığınıza bağlı. Örneğin, 'myVar' adlı global bir değişkenin var olup olmadığını görmek istiyorsanız, o window.myVarzaman yoksa 'undefined' döndürür. JavaScript'te 'tanımsız' olarak dönen tonlarca şey vardır, sadece 'null' döndüren tonlarca şey vardır - hepsi bağlama bağlıdır.
thdoan

2

Bazıları nesneleri başlatmanın uygun olduğunu söyledi null. Sadece yıkıcı argüman varsayılanlarının işe yaramadığını belirtmek istedim null. Örneğin:

const test = ({ name } = {}) => {
  console.log(name)
}

test() // logs undefined
test(null) // throws error

Bu, sıklıkla meydana gelebilecek işlevi çağırmadan öncenull kontrollerin yapılmasını gerektirir .


1

Şu anda tam olarak bu soru üzerinde çalışıyorum ve aşağıdaki felsefeye bakıyorum:

  1. Bir sonuç döndürmesi amaçlanan herhangi bir işlev, bir sonuç bulamazsa boş döndürmelidir.
  2. Sonuç döndürmesi amaçlanmayan herhangi bir işlev örtük olarak tanımsız döndürür.

Benim için bu soru önemlidir, çünkü sonuç döndüren bir işlevi çağıran herhangi birinin tanımsız ve null için test edip etmeme konusunda hiçbir sorusu olmamalıdır.

Bu cevap şunları ele almaya çalışmaz:

  1. Null ve undefined özellik değerleri
  2. İşlevlerinizdeki değişkenler null vs undefined

Bana göre, değişkenler sizin kendi işinizdir ve API'nizin bir parçası değildir ve herhangi bir OO sistemindeki özellikler tanımlanır ve bu nedenle tanımlanmadıkları takdirde olacaklarından farklı bir değerle tanımlanmalıdır (tanımlı için boş, tanımsız nesnenizde olmayan bir şeye erişirken olsun).


1

Bunun bir nedeni: var undefined = 1 yasal javascript, ancak var null = 1bir sözdizimi hatası. Aradaki fark, bu nullbir dil anahtar kelimesi iken undefined, bazı nedenlerden dolayı değil.

Kodunuz undefined, sanki bir anahtar kelimeymiş gibi karşılaştırmalara dayanıyorsa ( if (foo == undefined)- yapılması çok kolay bir hata), bu yalnızca hiç kimse bu adla bir değişken tanımlamadığından işe yarar . Tüm bu kodlar, yanlışlıkla veya kötü niyetle bu isimle bir global değişkeni tanımlayan birine karşı savunmasızdır. Elbette hepimiz javascript'te yanlışlıkla global bir değişkeni tanımlamanın tamamen imkansız olduğunu biliyoruz ...


1
void 0Tanımlanmamış yerine kullanın .
Frederik Krautwald

1

Sadece bazı javascript kitaplıklarının kullanılmasıyla null ve undefined'ın istenmeyen sonuçlara yol açabileceğini eklemek istiyorum.

Örneğin, getvarsayılan bir değeri 3. bağımsız değişken olarak kabul eden lodash işlevi:

const user = {
  address: {
    block: null,
    unit: undefined,
  }
}
console.log(_.get(user, 'address.block', 'Default Value')) // prints null
console.log(_.get(user, 'address.unit', 'Default Value')) // prints 'Default Value'
console.log(_.get(user, 'address.postalCode', 'Default Value')) // prints 'Default Value'

Başka bir örnek: React'te defaultProps kullanırsanız, bir özellik iletilirse null, null tanımlı bir değer olarak yorumlandığından varsayılan props kullanılmaz . Örneğin

class MyComponent extends React.Component {
   static defaultProps = {
      callback: () => {console.log('COMPONENT MOUNTED')},
   }
   componentDidMount() {
      this.props.callback();
   }
}
//in some other component
<MyComponent />   // Console WILL print "COMPONENT MOUNTED"
<MyComponent callback={null}/>   // Console will NOT print "COMPONENT MOUNTED"
<MyComponent callback={undefined}/>   // Console WILL print "COMPONENT MOUNTED"

0

Boş veya tanımsız kullanımının gereksiz olduğuna kesinlikle katılmıyorum. tanımsız, tüm prototip zincirleme sürecini canlı tutan şeydir. Dolayısıyla, yalnızca null değerine sahip derleyici, bu özelliğin null değerine eşit olup olmadığını veya uç nokta prototipinde tanımlanmadığını kontrol edemez. Diğer dinamik tipli dillerde (fe Python), tanımlanmamış özelliğe erişmek istiyorsanız istisna atar, ancak prototip tabanlı diller için derleyici ana prototipleri de kontrol etmelidir ve burada tanımsız en çok ihtiyaç duyulan yer burasıdır.

Null kullanmanın tüm anlamı, değişken veya özelliği tekil olan ve boşluk anlamına gelen nesneye bağlamaktır ve ayrıca boş kullanımın performans amacı vardır. Bu 2 kodun uygulama süresi farklıdır.

var p1 = function(){this.value = 1};
var big_array = new Array(100000000).fill(1).map((x, index)=>{
    p = new p1();
    if(index > 50000000){
       p.x = "some_string";
    }

    return p;
});
big_array.reduce((sum, p)=> sum + p.value, 0)

var p2 = function(){this.value = 1, p.x = null};
var big_array = new Array(100000000).fill(1).map((x, index)=>{
    p = new p2();
    if(index > 50000000){
       p.x = "some_string";
    }

    return p; 
});
big_array.reduce((sum, p)=> sum + p.value, 0)

undefinedprototip kalıtımının özel bir anlamı yoktur. Olarak ayarlanmış undefinedbir özellik, prototipten miras alınan bir özelliği (aynı ada sahip) yine de geçersiz kılacaktır.
Matthijs

0

Bilinmeyen değişken: undefined .

Bilinen değişken henüz hiçbir değer: null.

  1. Bir sunucudan bir nesne alırsınız, server_object .
  2. Sen referanssın server_object.errj. Sana olduğunu söylüyorundefined . Bu, onun ne olduğunu bilmediği anlamına gelir.
  3. Şimdi referans veriyorsun server_object.err. Size olduğunu söylüyor null. Bu, doğru bir değişkeni referans verdiğiniz anlamına gelir, ancak bu boş; bu nedenle hata yok.

Sorun, değeri olmayan bir değişken adı var hellotanımladığınızda ( ) js şunu bildirir undefined: bu değişken yok; programcılar çoğunlukla şu anlama gelir: "Henüz bir değer vermedim",null .

Dolayısıyla, bir programcının varsayılan davranışı - değeri olmayan bir değişkeni hiçbir şey olarak ilan etmek - js ile çelişir - onu mevcut değil olarak ilan eder. Ve üstelik, !undefinedve !nullher ikisi de truebu yüzden çoğu programcılar eşdeğer gibi davranarak.

Sen elbette her zaman yaptığın sağlamak olabilir var hello = nullama çoğu, kasten gevşek daktilo dilde tip aklı sağlayacak gibi çöp kodlarını olmaz onlar ne zaman ve !operatör tedavi hem undefinedve nulleşdeğer olarak.

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.