2010-05-26 4 views
104

Musiałem napisać procedurę, która zwiększa wartość zmiennej o 1, jeśli jej typ to number i przypisuje 0 do zmiennej, jeśli nie, gdzie początkowo jest zmienna null lub undefined.Dlaczego `null> = 0 && null <= 0`, ale nie` null == 0`?

Pierwsza implementacja to v >= 0 ? v += 1 : v = 0, ponieważ uważałem, że cokolwiek, a nie liczba, sprawiłoby, że wyrażenie arytmetyczne było fałszywe, ale było błędne, ponieważ null >= 0 zostało ocenione jako prawdziwe. Potem dowiedziałem się, że null zachowuje się jak 0, a wszystkie poniższe wyrażenia są prawdziwe.

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

Oczywiście null nie jest 0. null == 0 oceniana jest na false. To sprawia, że ​​pozornie tautologiczna ekspresja jest fałszywa.

Dlaczego jest null jak 0, chociaż w rzeczywistości nie jest 0?

+3

On mówi o JavaScript. Twój przykład jest w PHP. W PHP operator == porównuje wartości w specjalny sposób. Możesz dokonać naprawdę szalonych porównań, takich jak "10" == "1e1" (co jest prawdą). Jeśli użyłeś operatora ===, otrzymasz zupełnie inny wynik, ponieważ sprawdzi on, czy typ pasuje, a także wartość. Sprawdź ten link: http://www.php.net/manual/en/language.operators.comparison.php – Pijusn

+0

Operator PHP "==" naprawdę działa w "specjalny" sposób. –

+0

Jeśli Twoim wymaganiem było rozpoczęcie liczenia o wartości 1 zamiast 0, istnieje naprawdę zwięzły sposób zwiększania liczników, które początkowo mają wartość 'null' lub' undefined': 'c = - ~ c // Wyniki w 1 dla wartości null/undefined; inkrementacja, jeśli już ' –

Odpowiedz

160

Twoje prawdziwe pytanie wydaje się być:

Dlaczego:

null >= 0; // true 

Ale:

null == 0; // false 

Co naprawdę się dzieje, że Większy niż lub równy Operator (>=), wykonuje przymus typu (ToPrimitive), z podpowiedzią typ Number, faktycznie wszystkie operatory relacyjne mają takie zachowanie.

null jest traktowany w specjalny sposób przez operatora , który jest równy Operatorowi (==). W skrócie, to tylko wymusza do undefined:

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

Wartość takich jak false, '', '0' i [] podlegają numerycznej typu przymus, wszystkie z nich przymusić do zera.

Możesz zobaczyć wewnętrzne szczegóły tego procesu w The Abstract Equality Comparison Algorithm i The Abstract Relational Comparison Algorithm.

W skrócie:

  • Porównanie relacyjny: jeśli obie wartości nie są typu String, ToNumber nazywa się na obu. Jest to to samo, co dodanie z przodu +, które dla zerowych wiązań do 0.

  • Porównanie równości: tylko połączenia ToNumber na łańcuchach, liczbach i bajtach.

+1

Witam CMS, jak na twoje objaśnienie zerowy prymitywny to 0, więc 0> = 0 zwraca true, a == zwraca false.but jak na algorytm Ecma Jeśli Typ (x) to Obiekt i Typ (y) to Ciąg lub Numer , return the result ToPrimitive (x) == y.then w tym powinno zwrócić true. Proszę mi wyjaśnić –

+0

mi odpowiedź nie dostarcza * odpowiedzi * - 'null jest traktowany w specjalny sposób przez Równa się operatorowi (==). W skrócie, to tylko wymusza na undefined: '- i co? Czy możesz wyjaśnić, dlaczego 'null> = 0'? :) –

+0

@bharathmuppa @ andrey-deineko: Reszta odpowiedzi CMS jest tutaj: [The Abstract Relational Comparison Algorithm Algorithm] (http://www.ecma-international.org/ecma-262/5.1/#sec -11.8.5) , który wyjaśnia w punkcie 3., że jeśli obie wartości nie są typu String, w obu przypadkach wywoływana jest ToNumber. Jest to to samo, co dodanie przedrostka '+ ', które dla zerowych wymuszeń na' 0'. Równość wywołuje tylko ToNumber na Ciągach, Liczbach i Boolach. –

7

Chciałbym rozszerzyć pytanie do dalszej poprawy widoczności problemu:

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

To po prostu nie ma sensu. Podobnie jak języki ludzkie, te rzeczy trzeba się nauczyć na pamięć.

0

Miałem ten sam problem !!. Obecnie moim jedynym rozwiązaniem jest rozdzielenie.

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 ! 
3

JavaScript ma zarówno surowe i typu konwertazy porównań

null >= 0; prawda ale (null==0)||(null>0) jest fałszywa

null <= 0; jest prawdą, ale (null==0)||(null<0) jest fałszywa

"" >= 0 jest również prawdą

W przypadku relacyjnych porównań abstrakcyjnych (< =,> =) operandy są najpierw konwertowane na prymitywy, a następnie na ten sam typ, przed porównaniem.

typeof null returns "object"

Gdy typ jest obiektem JavaScript próbuje stringify obiektu (tj null) następujące kroki są podejmowane (ECMAScript 2015):

  1. Jeśli PreferredType nie została uchwalona, ​​niech hint być „default ".
  2. Inna, jeśli PreferredType jest hint String, niech hint będzie "ciągiem".
  3. Else PreferredType to hint Liczba, niech hint będzie "liczbą".
  4. Niech exoticToPrim będzie GetMethod(input, @@toPrimitive).
  5. ReturnIfAbrupt(exoticToPrim).
  6. Jeśli exoticToPrim nie jest niezdefiniowany, to
    a) Niech wynikiem będzie Call(exoticToPrim, input, «hint»).
    b) ReturnIfAbrupt(result).
    c) Jeśli Type(result) nie jest obiektem, wynik zwracany.
    d) Zgłasza wyjątek TypeError.
  7. Jeśli "hint" jest "domyślne", niech hint będzie "liczbą".
  8. Powrót OrdinaryToPrimitive(input,hint).

Dozwolone wartości wskazówki to "default", "number" i "string". Obiekty Date są unikalne wśród wbudowanych obiektów ECMAScript, ponieważ traktują "default" jako równoważne "string". Wszystkie inne wbudowane obiekty ECMAScript traktują "domyślny" jako równoważny "numerowi". (ECMAScript 20.3.4.45)

Więc myślę null konwertuje do 0.