2010-05-26 19 views
104

Ho dovuto scrivere una routine che incrementa il valore di una variabile di 1 se il suo tipo è number e assegna 0 alla variabile se non, dove la variabile è inizialmente null o undefined.Perché `null> = 0 && null <= 0` ma non` null == 0`?

La prima implementazione è stata v >= 0 ? v += 1 : v = 0 perché ho pensato che non un numero avrebbe reso falsa un'espressione aritmetica, ma è stato errato poiché null >= 0 è stato valutato come true. Poi ho appreso che null si comporta come 0 e le seguenti espressioni sono tutte valutate come vere.

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

Naturalmente, null non è 0. null == 0 è risultata falsa. Ciò rende falsa l'espressione apparentemente tautologica (v >= 0 && v <= 0) === (v == 0).

Perché lo null è uguale a 0, sebbene non sia effettivamente 0?

+3

Egli sta parlando di Javascript. Il tuo esempio è in PHP. Nell'operatore PHP == confronta i valori in un modo speciale. Puoi fare alcuni confronti davvero pazzi come "10" == "1e1" (che è vero). Se si utilizzava l'operatore ===, si otterrebbe un risultato completamente diverso perché controlla se il tipo corrisponde e anche il valore. Controlla questo link: http://www.php.net/manual/en/language.operators.comparison.php – Pijusn

+0

L'operatore PHP "==" funziona davvero in modo "speciale". –

+0

Se il tuo requisito era iniziare a contare a 1 invece che a 0, c'è un modo davvero esatto per incrementare i contatori inizialmente "nullo" o "non definito": 'c = - ~ c // Risultati in 1 per null/non definito; incrementi se già un numero ' –

risposta

160

tua vera domanda sembrano essere:

Perché:

null >= 0; // true 

Ma:

null == 0; // false 

Ciò che realmente accade è che il Maggiore di o uguale operatore (>=), esegue la coercizione di tipo (ToPrimitive), con un suggerimento di Number, in realtà tutti gli operatori relazionali hanno questo comportamento.

null viene trattato in modo speciale dalla Equals Operator (==). In breve, solo costringe a undefined:

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

Valore come false, '', '0' e [] sono soggetti a coercizione di tipo numerico, tutti costringerli a zero.

È possibile visualizzare i dettagli interni di questo processo in The Abstract Equality Comparison Algorithm e The Abstract Relational Comparison Algorithm.

In breve

  • relazionale confronto: se entrambi i valori non sono tipo stringa, ToNumber è chiamato su entrambi. Questo equivale ad aggiungere un + davanti, che per null va a 0.

  • Confronto di uguaglianza: chiama solo ToNumber su stringhe, numeri e booleani.

+1

Ciao CMS, come da spiegazione la primitiva nulla è 0, quindi 0> = 0 restituisce true e == restituisce false.but secondo l'algoritmo ecma Se Type (x) è Object e Type (y) è String o Number , restituisce il risultato del confronto ToPrimitive (x) == y.quindi in questo dovrebbe restituire true.please spiegami –

+0

per me la risposta non fornisce una * risposta * - 'null viene trattato in modo speciale dal Uguale all'operatore (==). In un breve, costringe solo a indefinito: '- e cosa? Puoi spiegare, perché 'null> = 0'? :) –

+0

@bharathmuppa @ Andrey-Deineko: Il resto della risposta di CMS è qui: [Il relazionale confronto Algorithm Abstract] (http://www.ecma-international.org/ecma-262/5.1/#sec -11.8.5) che spiega al punto 3. che se entrambi i valori non sono di tipo String, ToNumber viene chiamato su entrambi. È come aggiungere un '+' davanti, che per null costringe a '0'. L'uguaglianza chiama solo ToNumber su stringhe, numeri e booleani. –

7

mi piacerebbe estendere la domanda per migliorare ulteriormente la visibilità del problema:

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

Rende solo non ha senso. Come le lingue umane, queste cose devono essere apprese a memoria.

0

Ho avuto lo stesso problema !!. Attualmente la mia unica soluzione è separare.

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 ha entrambi i confronti severi e tipo di conversione

null >= 0; vale ma (null==0)||(null>0) è falso

null <= 0; è vero, ma (null==0)||(null<0) è falso

"" >= 0 vale anche

Per i confronti astratti relazionali (< =,> =), gli operandi vengono prima convertiti in primitive, quindi nello stesso tipo, prima del confronto.

typeof null returns "object"

Quando tipo è oggetto JavaScript tenta di stringa i all'oggetto (cioè null) le seguenti fasi vengono prese (ECMAScript 2015):

  1. Se PreferredType non è stato superato, lasciate hint essere "default ".
  2. Else se PreferredType è hint String, lasciate hint essere "string".
  3. Else PreferredType è hint Numero, cerchiamo hint essere "numero".
  4. Let exoticToPrim essere GetMethod(input, @@toPrimitive).
  5. ReturnIfAbrupt(exoticToPrim).
  6. Se exoticToPrim non è undefined, quindi
    a) Il risultato è Call(exoticToPrim, input, «hint»).
    b) ReturnIfAbrupt(result).
    c) Se Type(result) non è Oggetto, restituire il risultato.
    d) Generare un'eccezione TypeError.
  7. Se hint è "default", lasciare che hint essere "numero".
  8. Ritorno OrdinaryToPrimitive(input,hint).

I valori consentiti per hint sono "default", "numero" e "stringa". Gli oggetti data, sono unici tra l'oggetto ECMAScript incorporato in quanto trattano "default" come equivalente a "stringa". Tutti gli altri oggetti ECMAScript incorporati considerano "predefinito" come equivalente a "numero". (ECMAScript 20.3.4.45)

Quindi penso null converte a 0.

Problemi correlati