2010-10-20 11 views
13

Oggi ho avuto un'interessante domanda di intervista che mi ha un po 'impressionato. Mi è stato chiesto dei valori di falsità. Quindi undefined, NaN, null, 0 e una stringa vuota valutano tutti in falsi. Qual è la ragione per cui è utile sapere in JavaScript? L'unica cosa che posso pensare è invece di dover fare questo:Valori Falsey in JavaScript

if (mystring === '' || mystring === undefined) { } 

posso fare questo:

if (!mystring) 

È questo l'unica applicazione utile?

+8

NaN anziché NAn, null invece di Null (JavaScript fa distinzione tra maiuscole e minuscole) –

+0

Una delle cose che devi amare della programmazione è dover tenere il passo con i termini della lingua (inglese)."falso" è davvero un termine di programmazione legittimo o significa semplicemente "valori falsi"? Se è un termine reale, e non solo un geek, dove è un url che lo definisce, poiché non riesco a trovare una definizione legittima del termine. – Bill

+0

@Bill Suppongo che "verità" e "falsa" siano neologismi allora ... http://javascript.crockford.com/style2.html –

risposta

15

Un problema pericoloso dei valori di falsa cosa di cui bisogna essere a conoscenza è quando si controlla la presenza di una determinata proprietà.

Si supponga di voler verificare la disponibilità di una nuova proprietà; Quando questa proprietà può in realtà avere un valore di 0 o "", non si può semplicemente verificare la sua disponibilità utilizzando

if (!someObject.someProperty) 
    /* incorrectly assume that someProperty is unavailable */ 

In questo caso, è d'obbligo assegno al fatto che è realmente presente o no:

if (typeof someObject.someProperty == "undefined") 
    /* now it's really not available */ 

ricordiamo inoltre che NaN non è uguale a qualsiasi cosa, anche se non a se stesso (NaN != NaN).

+1

Ma puoi legittimamente impostare una proprietà su undefined, interrompendo così questo test. È quasi certamente meglio usare someObject.hasOwnProperty e controllarlo in modo ricorsivo se davvero ti interessa se la proprietà esiste ovunque nella catena di prototipi degli oggetti. – Angiosperm

+0

@Angiosperm In JavaScript, l'oggetto è dinamico in ogni caso, quindi non c'è alcuna differenza pratica tra un oggetto che non ha una proprietà e un oggetto che ha una proprietà impostata a "non definito" –

+0

@ Šime Vidas Scenario: la nostra applicazione chiama in qualche luogo remoto a controlla l'esistenza di una risorsa. L'esistenza della risorsa è costante durante il ciclo di vita dell'app. Questo controllo può essere costoso, quindi vogliamo iniziare a memorizzare nella cache il risultato della chiamata. Consente di impostare alcune proprietà di un oggetto sul risultato di tale chiamata. Il codice esistente controlla semplicemente se il risultato della chiamata è 'indefinito' per decidere se la risorsa esiste.Per non dover cambiare la nostra interfaccia attuale, il meccanismo della cache dovrebbe verificare se la proprietà appropriata esiste realmente, piuttosto che non è appena definita. – Angiosperm

3

E 'utile per rilevare se un browser è ha oggetti predefiniti specifici:

if(!!navigator.geolocation){ 
    // executes if the browser has geolocation support 
} 

if(!!document.createElement('canvas').getContext){ 
    // executes if the browser supports <canvas> 
} 

Spiegazione: navigator.geolocation è un oggetto o non definito. Nel caso in cui sia un oggetto, !navigator.geolocation restituirà false, se non è definito restituirà true. Quindi, per verificare se un browser ha abilitato la geolocalizzazione, devi "capovolgere" il booleano ancora una volta, aggiungendo un altro !.

+0

Quindi se l'ho fatto se (! Navigator.geolocation) {} ed è indefinito, questo restituirebbe false? –

+1

Non capisco ... Qual è la differenza tra "if (!! foo.bar)" e "if (foo.bar)"? –

+0

@elduderino No, restituirebbe true. Il ! l'operatore prima converte il suo operando in un valore booleano e poi lo commuta ... Nel caso in cui navigator.geolocation non sia definito, verrà convertito nel valore booleano falso, e quindi convertito in vero ... –

3

E 'importante sapere che 0 viene valutato come false per evitare di fare le cose come:

if(str.indexOf('foo')) 
+0

ah sì, molto bene. –

+0

Come funzionerebbe comunque? Restituisce -1 quando non viene trovato nulla, che non è un valore di falsa .. –

+0

@Nick: Il punto è che non funzionerebbe. –

3

Sono anche utile per impostare i valori di default ...

function foo(bar){ 
    alert(bar || "default"); 
} 

Conosco un sacco di persone cercano di fare

if (typeof(foo) === "undefined"){} 

per aggirare la falsità, ma quello che ho io ts propri problemi perché

typeof(null) === "object" 

per qualche motivo

+0

Sì, lo sapevo sul null. Strano. Buoni esempi. Grazie –

+0

@elduderine una cosa più bella di null isNIS (null) === false. – Angiosperm

+0

L'esempio (bar || "default") è probabilmente un antipattern. Questo perché si innescherà sulla stringa vuota che l'utente della funzione potrebbe aver inteso essere il valore della barra (ho trovato questo errore un numero di volte nelle librerie). Anche se il contesto significa che hai capito questo, non sarà chiaro all'utente della tua funzione che questo è il caso senza un commento. Meglio evitare questo stile completamente per valori che possono essere stringhe (""), numeri (NaN) o booleani (falso). – kybernetikos

5

E 'importante capire come funziona in JS, in modo da non siete sorpresi. Non necessariamente solo ciò che è falso, ma cos'è la verità e come si confrontano tra loro.

Un esempio è che '0' è considerato uguale a 0 con ==, ma non è uguale a '' - sebbene sia 0. Il confronto tra JavaScript non è sempre transitivo.

Questo significa che solo perché (foo==bar && bar==fizz) è vero, (foo==fizz) non è sempre vero. Per andare con l'esempio precedente, '0' == 0 e 0 == '', ma '0'! = '' - perché stai confrontando le stringhe nell'ultima istanza, quindi vengono confrontate come stringhe e non forzate ai numeri

7

Ci sono due problemi separati con i valori di "falso" in JavaScript.

In primo luogo c'è lo schema di conversione ufficiale, che è ciò che viene restituito da Boolean (x). Questo restituisce false quando x è false o 0 o NaN o null o undefined o "" e true altrimenti. Questo è lo stesso comportamento come il

if (condition) {/*true path*/} else {/*false path*/} 

che viene, viene eseguito il percorso false se booleana (condizione) avrebbe restituito falso e il vero cammino è eseguito al contrario. Questo comportamento viene spesso utilizzato per verificare se una proprietà è definita. Tuttavia, farlo non è sicuro se non si è certi che la proprietà sarebbe un oggetto o un array se è definito. Il modo più sicuro per verificare se una proprietà è definita è quello di fare

if (property != null) { /*property is defined*/} 

che fa in modo che la proprietà non è null o undefined. Se si desidera solo per assicurarsi che la proprietà non è indefinito fanno

if (property !== undefined) { /*property is not undefined (but may be null)*/ } 

(notare l'extra = a! ==).

In secondo luogo, ci sono tutti i valori che == false. Questo è tutto ciò che può essere forzato a 0 (che è ciò a cui falso viene forzato). Questo include tutti i valori che convertono in falso tranne NaN (che non può == falso in virtù di esso mai == nulla), null e indefinito. Ma include anche tutti gli oggetti che quando vengono convertiti in una stringa e poi convertiti in un numero sono uguali a 0. Ad esempio, questo include tutto ciò che una volta convertita in una stringa è la stringa vuota "" o "0" o "-0 "o "0" o "0x00" o "000" o "0E0" o "0.0000" ...., per esempio,

({toString: function() {return "-00.0e000";}}) == false 

è vero. È interessante notare che questo include l'array vuoto e qualsiasi nidificazione di array contenenti solo un singolo elemento che restituisce una stringa vuota o 0 poiché gli array resi come stringhe mostrano solo i contenuti senza le parentesi. Cioè,

[[[[0]]]] == false; // Because [[[[0]]]].toString() === "0" 
[] == false; 
[[[""]]] == false; 
["0"] == false; 
[[({toString: function() {return "0";}})]] == false; 

L'algoritmo completo per il calcolo == false è descritto here.

Il motivo per cui questo è importante perché può portare a bug sottili e difficili da trovare se non si capisce la maggior parte di queste regole. I takeaway più importanti sono probabilmente il modo in cui funziona lo if (condition) e che l'utilizzo di === evita la maggior parte delle altre cose pazzesche.

Problemi correlati