Perché c'è un valore "null" in JavaScript?


116

In JavaScript, ci sono due valori che sostanzialmente dicono "Non esisto" - undefinede null.

Una proprietà a cui un programmatore non ha assegnato nulla sarà undefined, ma affinché una proprietà lo diventi null, nulldeve essere assegnata esplicitamente ad essa.

Una volta ho pensato che fosse necessario nullperché undefinedè un valore primitivo e nullun oggetto. Non lo è, anche se typeof nullprodurrà 'object': in realtà, entrambi sono valori primitivi, il che significa che né undefinednullpossono essere restituiti da una funzione di costruzione, poiché entrambi verranno convertiti in un oggetto vuoto (si deve lanciare un errore per proclamare il fallimento nei costruttori).

Entrambi valutano anche falsein contesti booleani. L'unica vera differenza a cui riesco a pensare è che uno valuta a NaN, l'altro a 0in contesti numerici.

Allora perché ci sono entrambi undefinede nullse questo confonde solo i programmatori che stanno controllando in modo errato nullquando cercano di scoprire se una proprietà è stata impostata o meno?

Quello che vorrei sapere è se qualcuno ha un esempio ragionevole in cui è necessario usare nullche non potrebbe essere espresso usando undefinedinvece.

Quindi il consenso generale sembra essere che undefinedsignifica "non esiste tale proprietà" mentre nullsignifica "la proprietà esiste, ma non ha valore".

Potrei conviverci se le implementazioni JavaScript impongono effettivamente questo comportamento, ma undefinedè un valore primitivo perfettamente valido, quindi può essere facilmente assegnato alle proprietà esistenti per rompere questo contratto. Pertanto, se vuoi assicurarti che una proprietà esista, devi usare l' inoperatore o hasOwnProperty()comunque. Quindi ancora una volta: qual è l'uso pratico di valori separati per undefinede null?

In realtà lo uso undefinedquando voglio annullare l'impostazione dei valori delle proprietà non più in uso ma che non voglio delete. Dovrei usare nullinvece?


3
Per rispondere alla tua ultima domanda: No, non dovresti impostare le proprietà su undefined.
Shog9,

4
"undefined" è solo una variabile nell'ambito globale con il valore primitivo "undefined". È possibile definire un altro valore per la variabile: {undefined = "Hello"; alert (undefined);} Un modo più affidabile per testare undefined: {if (typeof myvar === "undefined") alert ("undefined")}
alcuni

1
Vedere la sezione 4.3.9 - 12 in ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf per undefined / null e 15.1.1.3 per la variabile "undefined" nell'ambito globale.
alcuni il

1
Dovresti eliminare un oggetto o impostarlo su null se ciò ha più senso, ma non su undefined.
alcuni il

4
In JavaScript, there are two values which basically say 'I don't exist' - undefined and null.No, undefineddice solo quello.
Gare di leggerezza in orbita

Risposte:


78

La domanda non è realmente "perché c'è un valore nullo in JS" - c'è un valore nullo di qualche tipo nella maggior parte delle lingue ed è generalmente considerato molto utile.

La domanda è: "perché c'è un valore indefinito in JS". Luoghi principali in cui viene utilizzato:

  1. quando si dichiara var x;ma non si assegna ad esso, xvale indefinito;
  2. quando la tua funzione ottiene meno argomenti di quelli che dichiara;
  3. quando si accede a una proprietà dell'oggetto inesistente.

nullavrebbe sicuramente funzionato altrettanto bene per (1) e (2) *. (3) dovrebbe davvero lanciare subito un'eccezione, e il fatto che non lo faccia, invece di restituire questo strano undefinedche fallirà in seguito, è una grande fonte di difficoltà di debug.

*: potresti anche sostenere che (2) dovrebbe generare un'eccezione, ma poi dovresti fornire un meccanismo migliore e più esplicito per argomenti predefiniti / variabili.

Tuttavia JavaScript non aveva originariamente eccezioni o alcun modo per chiedere a un oggetto se avesse un membro con un certo nome: l'unico modo era (e talvolta lo è ancora) accedere al membro e vedere cosa ottieni. Dato che nullaveva già uno scopo e potresti volerlo impostare un membro, era richiesto un valore diverso fuori banda. Quindi abbiamo undefined, è problematico come fai notare, ed è un'altra grande "funzionalità" di JavaScript di cui non saremo mai in grado di sbarazzarci.

In realtà utilizzo undefined quando desidero annullare l'impostazione dei valori di proprietà non più in uso ma che non voglio eliminare. Dovrei invece usare null?

Sì. Mantieni undefinedcome valore speciale per segnalare quando altre lingue potrebbero generare un'eccezione.

nullè generalmente migliore, tranne su alcune interfacce DOM IE dove l'impostazione di qualcosa nullpuò darti un errore. Spesso in questo caso l'impostazione sulla stringa vuota tende a funzionare.


10
Gli argomenti sono espandibili. Puoi inserirne quante ne vuoi e una funzione potrebbe potenzialmente iterarle e utilizzarle tutte. Agli oggetti può essere assegnata una nuova proprietà in qualsiasi momento. Queste sono entrambe potenti funzionalità, ma sospetto che le eccezioni lanciate come preferiresti sarebbero un sacco di sovraccarico. IMO, vale il compromesso. Trascorro molto meno tempo a verificare l'esistenza in JS di quanto non faccia di solito il casting in paradigmi linguistici più rigidi.
Erik Reppen

Buffo come la risposta accettata a una domanda inizi con "questa non è proprio la domanda ..."
Phillip

@ Bobince le prime versioni di JS non avevano l' inoperatore o hasOwnProperty? Perché sono molto più sicuri che obj.hello !== undefinedcontrollare se una proprietà esiste su un oggetto.
Andy

Non importa, ho risposto alla mia stessa domanda. Secondo MDN, sono stati entrambi introdotti in ES3.
Andy

37

Meglio descritto qui , ma in sintesi:

undefined è la mancanza di un tipo e di un valore e null è la mancanza di un valore.

Inoltre, se stai facendo semplici confronti "==", hai ragione, vengono fuori lo stesso. Ma prova ===, che confronta sia il tipo che il valore, e noterai la differenza.


1
Lo so null !== undefined- la mia domanda era perché ci fosse bisogno di due cose che esprimessero lo stesso concetto semantico; inoltre, il tuo link menziona che "null è un oggetto" - è sbagliato, è un primitivo ...
Christoph,

2
Non sono lo stesso concetto semantico. Almeno per me, c'è una differenza significativa tra una proprietà a cui viene assegnato un valore nullo e una proprietà non esistente.
Daniel Schaffer,

Ma è proprio così, non sono lo stesso concetto semantico. Null viene costretto quando si usa == a implicare la stessa cosa, per comodità del programmatore.
Eddie Parker,

1
@EricElliott: typeofbugie - leggi le specifiche o prova a tornare nullda un costruttore
Christoph

5
@EricElliott: il valore di ritorno dei costruttori non ha nulla a che fare con la falsità, ma con l'oggettività: se il valore di ritorno è un oggetto, restituiscilo; se è un primitivo come nullo 42, scartare il valore restituito e restituire invece l'oggetto appena creato
Christoph

17

Non credo che ci sia alcun motivo per avere entrambi nulle undefined, poiché l'unica ragione per cui molte persone hanno suggerito (" undefinedsignifica che non esiste una tale variabile / proprietà") non è valida, almeno in JavaScript. undefinednon può dirti se la variabile / proprietà esiste o meno.

console.log(foo);               // "ReferenceError: foo is not defined"
                                // foo does not exist
var foo;
console.log(foo);               // "undefined", a different response
console.log(foo === undefined); // "true", but it does exist

var obj = {};
console.log(obj.hasOwnProperty("foo")); // "false", no such property
obj.foo = undefined;
console.log(obj.hasOwnProperty("foo")); // "true", it exists and has the value "undefined"
console.log(obj.foo === undefined);     // "true", but it does exist

obj.bar = "delete me";
obj.bar = undefined;
console.log(obj.hasOwnProperty("bar")); // "true", not actually deleted
delete obj.bar;
console.log(obj.hasOwnProperty("bar")); // "false", deleted

Come puoi vedere, il controllo foo === undefinednon ti dice se fooesiste e l'impostazione obj.bar = undefinednon viene effettivamente eliminata bar.

Potrebbe essere l'intento originale dell'autore di JavaScript che undefineddovrebbe rappresentare la "non esistenza". Tuttavia, l'implementazione non è andata in questo modo.


1
Sostituisci undefinedcon nullnegli esempi di codice sopra e le risposte sono tutte uguali. Non sono sicuro di come questo risponda alla domanda. Era inteso come un commento alla risposta di qualcun altro?
Eric Elliott

1
@EricElliott La mia risposta alla domanda è che non c'è motivo di averli entrambi nulle undefined, perché l'unica ragione per cui molte persone hanno suggerito non è valida.
Lei Zhao

Dovresti modificare la tua risposta e dirlo effettivamente. Avrei potuto votare se mi avessi dato quella risposta. =)
Eric Elliott

@EricElliott Penso che tu abbia ragione. Ho modificato la mia risposta. Grazie!
Lei Zhao

3
Questo esempio mostra effettivamente che se non hai assegnato una variabile, restituisce undefined. Ma se lo hai assegnato undefined, in realtà non lo è undefined: è stato definito con undefinede fa riferimento ad esso. L'unica differenza tra undefinede nullè il loro utilizzo e lo scopo storico. Sono entrambi atomici.
Aleksej Komarov

6

È del tutto possibile aver bisogno di entrambi. Ad esempio, se si esegue una query su WMI, è del tutto possibile avere proprietà di ritorno di una classe che hanno un valore nullo. Sono definiti, capita che siano nulli al momento.


6

Penso che la tua conclusione che JavaScript definisce undefinedcome "non esiste tale proprietà" enull come "la proprietà non ha valore" sia perfettamente corretta. E in un linguaggio dinamico come JavaScript è una distinzione molto importante. L'uso della dattilografia significa che dobbiamo essere in grado di distinguere tra una proprietà che non esiste e che non ha un valore. È il nostro mezzo principale per ricavare informazioni sul tipo. in un linguaggio tipizzato staticamente esiste una netta distinzione tra un campo nullo e un campo non esistente. In JavaScript questo non è diverso. Tuttavia è controllato in fase di esecuzione e può essere modificato fino a quel momento.

Devo ammettere che l'implementazione è strana poiché molte volte la distinzione è offuscata. Tuttavia penso che in JavaScript la distinzione sia importante. E poter assegnareundefined è essenziale.

Ricordo di aver letto un post sul blog qualche tempo fa su un gioco di ruolo online scritto in JavaScript. Ha utilizzato esempi in cui gli oggetti sono stati creati come copie di istanze esistenti piuttosto che prototipi (classi, funzioni, qualsiasi cosa) e sono stati quindi modificati. Questo mi ha fatto davvero capire quanto undefinedpotesse essere potente quando si modificano oggetti esistenti, ma non ricordo chi l'abbia scritto.


Potresti condividere questo gioco di ruolo?
Michael

3

Semanticamente significano cose diverse. Il tipo null ha esattamente un valore nel suo dominio, null e a una proprietà può essere assegnato questo valore specifico. Undefined rappresenta una netta mancanza di valore assegnato.


1
ma puoi usare undefinedbenissimo per assegnare alle proprietà, quindi questo contratto (restituire solo undfinedse non esiste tale proprietà) può essere facilmente infranto dal programmatore ...
Christoph

2
È possibile , ma sicuramente non dovrebbe. Undefined è usato come una forma di eccezione molto semplice / semplicistica in JavaScript: non usarlo come valore e assegnarlo a qualche proprietà! È un pazzo.
rfunduk

3

Come programmatore Java, vedo un'enorme differenza tra undefined e null. Codificare JavaScript, non tanto, perché JavaScript non è fortemente tipizzato e le differenze tra undefined e null sono offuscate dalle conversioni automatiche che vengono eseguite frequentemente in fase di esecuzione. A proposito, approfitto spesso di queste conversioni; rendono il mio codice JS più compatto e leggibile.

Per rispondere alla tua domanda, undefined significa che un valore non è mai stato impostato. In pratica, questo generalmente indica un bug. Se yourObject.property non è definito, significa che non hai impostato la proprietà per qualche motivo o sto cercando qualcosa che non esiste affatto. Questo è un vero problema quando si lavora su un progetto con più di un codificatore.

null significa che "nessun valore" è stato impostato esplicitamente. In pratica, mi stai dicendo qualcosa sulla proprietà, forse che non è utilizzata in questo contesto, o che un valore deve ancora essere determinato.

In Java, i tentativi di accedere a un campo non definito genereranno sempre un'eccezione. In effetti, il compilatore può essere creato per avvisarti di questo nel tuo codice.


0

Prova questo esempio:

<html>
<head>
    <script type="text/javascript">
        function ShowObjProperties(obj) {
            var property, propCollection = "";

            for(property in obj) {
                propCollection += (property + ": " + obj[property] + "\n");
            }

            alert(propCollection);
        }

        var obj = {
            userid: 3,
            name: 'me!',
            speak: function() { alert('Hi! My name is ' + this.name + ' and my ID is ' + this.userid + '.'); }
        }

        //Shows all properties
        ShowObjProperties(obj);

        //The Speak function is no longer in the list!
        delete obj.speak;
        alert(typeof obj.speak);
        ShowObjProperties(obj);

        //The UserID is still listed, it just has no value!
        obj.userid = null;
        ShowObjProperties(obj);
    </script>
</head>
<body>

</body>
</html>

Penso che qui ci sia un uso molto reale per 2 tipi diversi.


E nei prototipi penso che sia un membro nullo o semplicemente indefinito.
Kev,

ma funziona solo fino a quando nessuno cerca di romperlo - se imposto obj.userid = undefined, fallirà - vedi l'ultima modifica alla mia domanda
Christoph,

0

Ciò che ne consegue è la natura dinamica di javascript.

Le cose potrebbero non essere definite in modo che possano essere aggiunte in un secondo momento. Questo è probabilmente il motivo per cui javascript è così potente ed estensibile.


e questo è rilevante per la mia domanda in che modo?
Christoph,

2
È rilevante perché risponde alla tua domanda. "null" è una sorta di "singleton" che significa "non ha valore". "undefined" ti sta dicendo che qualcosa è ... scioccante, lo so ... non definito. Sono cose completamente diverse.
rfunduk

0

è una caratteristica del linguaggio importante se avvolgi il tuo programma attorno al paradigma con eventi di javascript.

// a key exists as a placeholder for something
if(obj[name] === null) 
// no key exists int eh hashtable that is in this object
if(obj[name] === undefined)

questo è molto utile se hai a che fare con un insieme di dati che necessita di un valore per rappresentare "niente" per indicare un'azione diversa dall'uso di "niente" per indicare l'azione predefinita.

filter_func_pt = {
  date:function(d){ return Math.round(d.getTime()/1000);},
  user: null,
}

function transform(obj){
    var ret = {};
    for( var prop in obj){
       var f = filter_func_pt[prop];
       if(f)
          ret[prop] = f(obj);
       else if(filter_func_pt[prop] === null)
         continue;
       else
         ret[prop] == obj;
    }
  return ret;
}

var a = {
   date: new Date(),
   user: 'sam'
   votes: [23, 41, 55] 
};

var b = transform(a);

/* b = {
 *    date: 1298582417
 *    votes: [23, 41, 55]
 * }
 */

nel codice sopra la parola chiave null e il server undefined scopi molto chiari e diversi. la ricerca che non si trova nell'oggetto filter_func_pt che restituisce undefined significa aggiungere la proprietà all'oggetto restituito così com'è, mentre un valore nullo indica che il valore deve essere trattenuto, e non aggiunto, e la presenza di qualsiasi valore vero in questo case rappresenta una funzione utilizzata per trasformare il valore prima di aggiungerlo all'oggetto ret .


Questo esempio è artificioso e un po 'senza senso. Null non chiarisce affatto il tuo intento, piuttosto lo maschera. Avresti potuto usare una stringa più esplicita per chiarire il significato. Ad esempio, "withhold" o "strip" e quindi potresti anche essere più esplicito sul tipo di funzione e verificare effettivamente la presenza di una funzione.
Eric Elliott

0

null è bello

come tutti gli altri tipi di Live Script.

cite: In JavaScript, ci sono due valori che fondamentalmente dicono "Io non esisto": undefined e null.

Perché vorresti dire cose sbagliate ?!

"null" è "oggetto vuoto" proprio come "0" è un "numero vuoto" . 0, non è nulla, ma esiste come oggetto Tipo di numero. Ovviamente anche null è vuoto ma "lo è" ed è una cosa ben definita di un tipo di oggetto .

È comune parlare di queste cose come di "tipi", quando non lo sono. In realtà sono "categorie". Ma adesso è finita.

Quindi continuerò a dire che "null" è un tipo di oggetto senza un tipo. E "null" dice "io esisto [!], Ma non ho contenuti della mia specie".

Considerando che undefined manca sia del Type che del Kind, dove undefined è anche la sua definizione di Type. Un tipo indefinito di un tipo diventa la sua tipologia distintiva. Una sorta di domanda [non esiste "niente" e come definisci "niente"?].

cite: undefined né null possono essere restituiti da una funzione di costruzione, poiché entrambi saranno convertitori in un oggetto vuoto

Sei riuscito a dire ancora una volta una cosa sbagliata. Ovviamente no, l '"indefinito" non è un Oggetto, è un semplice Segno che noi umani comprendiamo; ma contrariamente a quel null è - e ti sta dicendo che: il suo Tipo è corretto, ma il Tipo che stai cercando non è contenuto al suo interno, o almeno - non in questo momento. Vieni a trovarci più tardi, quando inseriremo \ assegna qualche oggetto \ ad esso.

cita: L'unica vera differenza a cui riesco a pensare è che uno valuta NaN, l'altro 0 in contesti numerici.

Ciò rende l'intero punto della loro distinzione principale, come accennato: undefined è un semplice segno e poiché è costituito dallo stesso materiale 'genetico' dei suoi lontani parenti: stringhe, l'operazione [+ undefined] lo convertirà in anatra NaN, allo stesso modo null ovviamente si trasformerà in un tipo corretto 0 \ Number, e al contrario di undefined che si trasformerà in una stringa (! Che non è vuota!) Ed è esattamente per questo che restituisce NaN . Dove: + undefined >> + "undefined" >> NaN. Poiché il contesto numerico si aspetta un valore esplicito.

Mentre il contesto booleano si aspetta un riferimento, non trova nulla da convertire e restituisce "falso".

Tagliamo adesso ...

cite: Quindi ancora una volta: qual è l'uso pratico di valori separati per undefined e null?

Cercherò di darvi solo due esempi empirici e spero di bastare

oElement.onclick >> null

// significa che la proprietà esiste; il suo valore atteso è di Type: Object e che oElement supporta l'evento "onclick"!

oElement.innerText >> ""

// significa - la proprietà esiste; il suo valore atteso è di Tipo: String , il che significa che oElement supporta la proprietà "innerText".

in entrambi i casi -se ricevi "undefined" significa che la proprietà non esiste; non è supportato o ha un'implementazione sbagliata (ua vendor).

Resta al gelo e divertiti.


Non vandalizzare i tuoi post, Enea. Eliminali (utilizzando il pulsante Elimina appena sopra questo commento) se desideri rimuovere il tuo contributo.
Michael Petrotta

non c'è alcun pulsante di cancellazione, ma nel caso in cui lo vedi, fai clic su di esso!

0

dopo aver letto un'incredibile discussione su undefined vs null, una piccola ricerca su Google mi ha portato a Mozilla Documentations https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null è menzionato - null è spesso recuperato in un luogo in cui ci si può aspettare un oggetto ma nessun oggetto è rilevante.

Non è simile al pattern oggetto Null https://en.wikipedia.org/wiki/Null_object_pattern

Quindi immagino che abbia senso avere un tipo di dati Null.

Documentazione indicata anche come typeof null // "object" (non "null" per motivi legacy)

Non sono sicuro di quali siano le ragioni del passato

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.