Neden `null> = 0 && null <= 0` ama` null == 0` değil?


142

Bir değişkenin değeri 1 ise number, değişken ise başlangıçta nullveya değişkense değişkene 0 atarsa , rutin yazmak zorunda kaldım undefined.

İlk uygulama, v >= 0 ? v += 1 : v = 0bir sayı olmayan herhangi bir şeyin aritmetik bir ifadeyi yanlış yapacağını düşündüm, ancak doğru olarak null >= 0değerlendirildiğinden yanlıştı . Sonra öğrendim ki null0 gibi davranıyor ve aşağıdaki ifadelerin hepsi doğru olarak değerlendiriliyor.

  • null >= 0 && null <= 0
  • !(null < 0 || null > 0)
  • null + 1 === 1
  • 1 / null === Infinity
  • Math.pow(42, null) === 1

Tabii ki, null0 değil null == 0yanlış olarak değerlendirilir. Bu görünüşte totolojik ifadeyi (v >= 0 && v <= 0) === (v == 0)yanlış yapar .

nullAslında 0 olmasa da neden 0 gibidir?


3
Javascript hakkında konuşuyor. Örneğiniz PHP biçimindedir. PHP işlecinde == değerleri özel bir şekilde karşılaştırır. "10" == "1e1" (ki bu doğru) gibi gerçekten çılgın karşılaştırmalar yapabilirsiniz. === operatörünü kullandıysanız, türün değerle eşleşip eşleşmediğini kontrol ettiği için tamamen farklı bir sonuç elde edersiniz. Bu bağlantıya göz atın: php.net/manual/en/language.operators.comparison.php
Pijusn

PHP '==' operatörü gerçekten "özel" bir şekilde çalışıyor.
İki Bit Simyacı

Gereksiniminiz 0 yerine 1'de saymaya başlamaksa, başlangıçta ya nullda şu sayaçları artırmak için gerçekten kısa bir yol var undefined:c = -~c // Results in 1 for null/undefined; increments if already a number
Ates Goral

1
undefinedbaşlatılmamış değişkenler için bir değişken değerdir. nullÖte yandan, boş bir nesne değeridir ve sayılarla karıştırılmamalıdır. nullsayılarla birleştirilmemelidir, bu nedenle null değerinin sayılar gibi davranması gerekmez.
Matthew

1
@AtesGoral - kısa ama açık değil. Açık bir şey yaparken, kodun ne yaptığını açıklayan bir yorum eklemek için insanlara hatırlatmaya değer. Çoğu durumda, küçük bir performans kazancı için netlik kazandırdığı göz önüne alındığında, bunu bir "erken optimizasyon" olarak değerlendiririm.
ToolmakerSteve

Yanıtlar:


207

Gerçek sorunuz şu şekilde görünüyor:

Neden:

null >= 0; // true

Fakat:

null == 0; // false

Gerçekte olan şey şudur: Büyüktür veya eşittir Büyük İşleç ( >=), ToPrimitivebir tür ipucu ile tip zorlama ( ) gerçekleştirir Number, aslında tüm ilişkisel işleçler bu davranışa sahiptir.

nullEşittir Operatörü ( ==) tarafından özel bir şekilde ele alınır . Kısacası, sadece şunları yapmaya zorlarundefined :

null == null; // true
null == undefined; // true

Değer gibi false, '', '0've []hepsi sıfıra sayısal tip zorlama tabi zorlamak edilir.

Bu sürecin iç detaylarını Soyut Eşitlik Karşılaştırma Algoritması ve Soyut İlişkisel Karşılaştırma Algoritması'nda görebilirsiniz .

Özetle:

  • İlişkisel Karşılaştırma: her iki değer de Dize değilse ToNumber, her ikisinde de çağrılır. Bu, +null zorlamalara öndeki bir ekleme ile aynıdır 0.

  • Eşitlik Karşılaştırması: yalnızca ToNumberDizgiler, Sayılar ve Boole'lara çağrı yapar.


1
Merhaba CMS, açıklamanıza göre null ilkel 0 olduğundan, 0> = 0 true değerini döndürür ve ==, ecma algoritmasına göre false.but döndürür. Type (x) Object ve Type (y), String veya Number ise, karşılaştırmanın sonucunu döndürmek ToPrimitive (x) == y. ondan sonra bu doğru dönmelidir. lütfen açıklayın
bharath muppa 6

Bana cevap bir sağlamaz cevabı - null is treated in a special way by the Equals Operator (==). In a brief, it only coerces to undefined:- ve ne? Açıklayabilir misiniz, neden null >= 0? :)
Andrey Deineko

@bharathmuppa @ andrey-deineko: CMS'nin cevabının geri kalanı burada: 3. noktada açıklayan Soyut İlişkisel Karşılaştırma Algoritması , her iki değer de String değilse, her ikisi için de ToNumber çağrılır. Bu, +null zorlamalara öndeki bir ekleme ile aynıdır 0. Eşitlik yalnızca Dizeler, Sayılar ve Boole'larda ToNumber'ı çağırır.
Michael Liquori

7
İyi açıklama, ama hoşuma gitmedi. Herhangi bir dilde (x == 0 || x> 0) (x> = 0) ile eşdeğer olmalıdır. javascript aptal bir dildir.
John Henckel

1
Bu sadece spec bir hata gerçekten (çünkü matematiksel olarak yanlış) ve milyonlarca web sitesi boş karşılaştırmalar dayanmaktadır çünkü bu konuda yapacak bir şey yok ^^ '
mahieddine

14

Sorunun görünürlüğünü daha da artırmak için soruyu genişletmek istiyorum:

null >= 0; //true
null <= 0; //true
null == 0; //false
null > 0;  //false
null < 0;  //false

O sadece hiçbir anlam ifade etmiyor. İnsan dilleri gibi, bunların da yürekten öğrenilmesi gerekir.


1
Yukarıda açıklandığı gibi, == null değerinin nasıl davrandığı istisnası ile açıklanabilir, aksi takdirde null, Number (nulll) kullanılarak 0'a dönüştürülür
Ranka

5

JavaScript'in hem katı hem de tür dönüştüren karşılaştırmaları vardır

null >= 0;doğru ama (null==0)||(null>0)yanlış

null <= 0;doğru ama (null==0)||(null<0)yanlış

"" >= 0 ayrıca doğru

İlişkisel soyut karşılaştırmalar için (<=,> =), işlenenler önce ilkellere, daha sonra karşılaştırmadan önce aynı türe dönüştürülür.

typeof null returns "object"

Tür nesne olduğunda javascript nesneyi dizgi yapmaya çalıştığında (yani null) aşağıdaki adımlar uygulanır ( ECMAScript 2015 ):

  1. Eğer PreferredTypegeçti değildi, let hint"varsayılan" olmak.
  2. Else PreferredType, hintString ise , hint"string" olsun.
  3. Else PreferredTypeolduğunu hintNumara izin hint"sayı" olması.
  4. Let exoticToPrimolmak GetMethod(input, @@toPrimitive).
  5. ReturnIfAbrupt(exoticToPrim).
  6. Eğer exoticToPrimtanımsız değil, o
    bir) sonucu olalım Call(exoticToPrim, input, «hint»).
    b) ReturnIfAbrupt(result).
    c) Type(result)Nesne değilse sonucu döndürün.
    d) TypeError istisnası atın.
  7. Eğer hint"varsayılan" olduğunu let hint"numara" olmak.
  8. Dönüş OrdinaryToPrimitive(input,hint).

İpucu için izin verilen değerler "varsayılan", "sayı" ve "dize" dir. Tarih nesneleri, yerleşik ECMAScript nesnesi arasında benzersizdir, çünkü "varsayılan" a "dizeye" eşdeğer olarak davranırlar. Diğer tüm yerleşik ECMAScript nesneleri "default" u "number" ile eşdeğer olarak kabul eder . ( ECMAScript 20.3.4.45 )

Bence null0'a dönüşüyor.


1

Aynı sorunu yaşadım !! Şu anda benim tek çözüm ayırmak.

var a = null;
var b = undefined;

if (a===0||a>0){ } //return false  !work!
if (b===0||b>0){ } //return false  !work!

//but 
if (a>=0){ } //return true !

Yerine ne O daha net olabilir: if (a!=null && a>=0). Bu, yalnızca >=kendi başına yapmamanın nedenini açıklığa kavuşturur : "a null (veya tanımsız olabilir, bu da '== null')".
ToolmakerSteve

0
console.log( null > 0 );  // (1) false
console.log( null == 0 ); // (2) false
console.log( null >= 0 ); // (3) true

Matematiksel olarak, bu garip. Son sonuç, "null değerinin sıfıra eşit veya daha büyük" olduğunu belirtir, bu nedenle yukarıdaki karşılaştırmalardan birinde doğru olması gerekir, ancak her ikisi de yanlıştır.

Bunun nedeni, eşitlik kontrolü ==ve karşılaştırmanın > < >= <=farklı şekilde çalışmasıdır. Karşılaştırmalar, null değerini sayı olarak dönüştürür 0. (3) Bu yüzden null >= 0olduğunu trueve (1) null > 0olduğunu false.

Öte yandan, eşitlik onay ==için undefinedve nullherhangi bir dönüşümle olmadan, birbirlerini eşit ve başka eşit bir şey yok, öyle ki tanımlanır. (2) Bu yüzden null == 0olduğunu false.

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.