Che motivo c'è per utilizzare null invece di undefined in JavaScript?


103

Scrivo JavaScript da molto tempo ormai e non ho mai avuto motivo di utilizzarlo null. Sembra che undefinedsia sempre preferibile e abbia lo stesso scopo a livello di programmazione. Quali sono alcuni motivi pratici da utilizzare al nullposto di undefined?


Questo è un possibile duplicato di stackoverflow.com/questions/461966/...
lawnsea

Beh, ci sono metodi del genere document.getElementById()che possono restituire nullma no undefined, quindi in quei casi perché dovresti testare il reso undefined? (Certo, funzionerebbe se usassi ==piuttosto che ===, ma comunque, perché dovresti testare deliberatamente la cosa sbagliata?)
nnnnnn

Può essere utile avere tipi prevedibili e questo può guidare il pensiero a usare l'uno o l'altro. Quando un oggetto viene sempre restituito, necessario o voluto dalla progettazione, utilizzare null per risultati falsi (ad esempio document.getElementById('does-not-exist')). Le variabili var a;e i valori restituiti dalle funzioni sono predefiniti come non definiti. In passato null era nell'ambito globale, quindi il suo utilizzo rallentava l'esecuzione e mi portava a preferire altri tipi falsi (false, ", 0) ai riferimenti liberi. Personalmente evito null a meno che non ci sia una ragione convincente altrimenti perché lo percepisco come più semplice, che è generalmente migliore.
jimmont

Risposte:


59

Null e undefined sono essenzialmente due valori diversi che significano la stessa cosa. L'unica differenza è nelle convenzioni di come li usi nel tuo sistema. Come alcuni hanno accennato, alcune persone usano null per indicare "nessun oggetto" dove a volte potresti ottenere un oggetto mentre undefined significa che non era previsto alcun oggetto (o che si è verificato un errore). Il mio problema con questo è completamente arbitrario e totalmente inutile.

Detto questo, c'è una differenza principale: le variabili che non sono inizializzate (inclusi i parametri della funzione in cui non è stato passato alcun argomento, tra le altre cose) sono sempre indefinite.

Ecco perché nel mio codice non uso mai null a meno che qualcosa che non controllo non restituisca null (ad esempio, corrispondenza regex). Il bello di questo è che semplifica molto le cose. Non devo mai controllare se x === undefined || x === null. E se hai l'abitudine di usare == o semplicemente cose come if (x) .... Smettila. !xrestituirà true per una stringa vuota, 0, null, NaN, ovvero cose che probabilmente non vuoi. Se vuoi scrivere javascript che non sia orribile, usa sempre triple uguale === e non usare mai null (usa invece undefined). Ti semplificherà la vita.


137
Non sono d'accordo con questo. Null viene utilizzato per definire qualcosa di programmaticamente vuoto. Indefinito significa che il riferimento non esiste. Un valore nullo ha un riferimento definito a "niente". Se stai chiamando una proprietà non esistente di un oggetto, diventerai indefinito. Se desidero rendere quella proprietà intenzionalmente vuota, deve essere nulla in modo da sapere che è apposta. Molte librerie javascript funzionano in questo modo.
com2ghz

6
@ com2ghz Ciò che descrivi è una delle tante filosofie. Molte librerie js funzionano davvero in questo modo. Molti inoltre non funzionano in questo modo. In javascript, puoi memorizzare un valore esplicito non definito in un oggetto o array con la stessa facilità con cui puoi farlo con null. I significati di entrambi dipendono completamente e interamente dal contesto. Cioè significano quello che vuoi che significhino.
BT

3
Ecco perché JS è un linguaggio orribile. Come dici tu, molte biblioteche hanno le loro filosofie ma tu includi molte biblioteche per 1 progetto. Quindi incontri molte convenzioni di quelle librerie. Quante volte hai bisogno di fare diversi controlli falsi. Non sarebbe l'ultima volta che si concatena un oggetto null a una stringa e si ottiene un "null" come stringa. O passando uno 0 come valore numerico e chiedendosi perché l'istruzione IF gestisce è t come falso.
com2ghz

2
@ com2ghz Quindi JS è un linguaggio orribile perché ha sia null che undefined? Posso contare dozzine di cattive decisioni linguistiche in tutte le principali lingue, js non fa eccezione. Non ho letteralmente mai bisogno o voglio usare controlli falsi nel mio codice e uso sempre ===o !==. JS è un linguaggio straordinariamente espressivo se sai come usarlo.
BT

6
Destra. Ho appena appreso che la dicotomia null/ undefinedera necessaria perché la versione iniziale di JS non aveva hasOwnPropertyné l' inoperatore. Ora che lo fa, non capisco davvero perché uno di loro non sia stato abolito in ES6 o in qualsiasi proposta ES7 che ho visto.
Andy

86

Non ho davvero una risposta, ma secondo Nicholas C. Zakas , pagina 30 del suo libro " JavaScript professionale per sviluppatori Web " :

Quando si definisce una variabile che in seguito deve contenere un oggetto, è consigliabile inizializzare la variabile a nullinvece di qualsiasi altra cosa. In questo modo, puoi verificare esplicitamente il valore nullper determinare se la variabile è stata riempita con un riferimento a un oggetto in un secondo momento


8
+1 si, sono d'accordo e cerco sempre di ricordarmi di inizializzare vars su null. Allora sono (abbastanza) sicuro che questo undefinedsignifichi che è successo un disastro. Solo imho.
Pete Wilson

9
@ Pete - ma non ti dice nulla sul "disastro", quindi qual è il punto? E puoi fare questo presupposto solo se sai che la funzione segue la convenzione.
RobG

7
D'altra parte, puoi anche inizializzare la variabile con var myVar;e controllare esplicitamente il valore undefinedper determinare se è stato riempito con un riferimento a un oggetto in un secondo momento. Il punto è che questo è totalmente accademico: puoi farlo in entrambi i modi, e chiunque dia consigli in un modo piuttosto che nell'altro sta semplicemente spingendo la propria convenzione.
Thdoan

1
L'unico problema che ho (da quando ho iniziato con JavaScript 15 anni fa) è che troppo spesso devi testare undefinede null. Questo è ancora davvero fastidioso. Evito di assegnare una variabile a nullsolo per ridurre il numero di nulltest extra .
G Man

4
@GMan - Questo è l'unico posto in cui il ==confronto (al contrario di ===) ha senso: v == null(o v == undefined) verificherà se è nullo o non definito.
Rick Love

14

Alla fine della giornata, poiché entrambi nulle undefinedcostringono allo stesso valore ( Boolean(undefined) === false && Boolean(null) === false), puoi tecnicamente utilizzare entrambi per portare a termine il lavoro. Tuttavia, c'è il modo giusto, IMO.

  1. Lascia l'utilizzo di undefinedal compilatore JavaScript.

    undefinedviene utilizzato per descrivere variabili che non puntano a un riferimento. È qualcosa che il compilatore JS si prenderà cura di te. In fase di compilazione, il motore JS imposterà il valore di tutte le variabili sollevate su undefined. Quando il motore passa attraverso il codice ei valori diventano disponibili, il motore assegnerà i rispettivi valori alle rispettive variabili. Per quelle variabili per le quali non ha trovato valori, le variabili continuerebbero a mantenere un riferimento alla primitiva undefined.

  2. Utilizzare null solo se si desidera esplicitamente indicare il valore di una variabile come "nessun valore".

    Come afferma @ com2gz: nullviene utilizzato per definire qualcosa di programmaticamente vuoto. undefinedsignifica che il riferimento non esiste. Un nullvalore ha un riferimento definito a "niente". Se stai chiamando una proprietà inesistente di un oggetto, otterrai undefined. Se rendessi quella proprietà intenzionalmente vuota, allora deve essere nullcosì che tu sappia che è apposta.

TLDR; Non usare la undefinedprimitiva. È un valore che il compilatore JS imposterà automaticamente quando dichiari variabili senza assegnazione o se provi ad accedere a proprietà di oggetti per i quali non c'è riferimento. D'altra parte, usa nullse e solo se vuoi intenzionalmente che una variabile non abbia "nessun valore".

Non ho mai impostato esplicitamente nulla su undefined (e non l'ho riscontrato nelle molte basi di codice con cui ho interagito). Inoltre, uso raramente null. Le uniche volte che uso nullè quando voglio indicare il valore di un argomento a una funzione come privo di valore, ovvero:

function printArguments(a,b) {
  console.log(a,b);
}

printArguments(null, " hello") // logs: null hello

Questa avrebbe dovuto essere la risposta selezionata
alaboudi

13

indefinito è dove non esiste la nozione della cosa; non ha tipo e non è mai stato referenziato prima in tale ambito; null è dove si sa che la cosa esiste, ma non ha valore.


4
Come fai a sapere se è stato effettuato un tentativo di assegnare un valore, ma non è riuscito e invece è stato assegnato undefined ?
RobG

11

Ognuno ha il proprio modo di codificare e la propria semantica interna, ma negli anni ho scoperto che questo è il consiglio più intuitivo che do a chi fa questa domanda: in caso di dubbio, fai quello che fa JavaScript .

Supponiamo che tu stia lavorando con proprietà di oggetti come le opzioni per un plugin jQuery ... chiediti quale valore JavaScript dà a una proprietà che deve ancora essere definita - la risposta è undefined. Quindi, in questo contesto, inizializzerei questi tipi di cose con "undefined" per essere coerente con JavaScript (per le variabili, puoi farlo var myVar;invece di var myVar = undefined;).

Supponiamo ora che tu stia manipolando DOM ... quale valore assegna JavaScript a elementi inesistenti? La risposta è null. Questo è il valore con cui inizializzerei se stai creando una variabile segnaposto che in seguito conterrà un riferimento a un elemento, frammento di documento o simile che si riferisce al DOM.

Se stai lavorando con JSON, è necessario creare un caso speciale: per valori di proprietà non definiti, dovresti impostarli ""o nullperché un valore di undefinednon è considerato formato JSON corretto.

Detto questo, come ha affermato un poster precedente, se scopri che stai inizializzando qualcosa con nullo undefinedpiù di una volta in una luna blu, allora forse dovresti riconsiderare come procedere per la codifica della tua app.


Anche se questo è un buon atteggiamento, vorrei aggiungere questa risposta: stackoverflow.com/a/37980662/883303
Frederik Krautwald

@FrederikKrautwald grazie per il collegamento - questa è una delineazione molto chiara.
Thdoan

10

Potresti adottare la convenzione suggerita qui, ma non c'è davvero nessuna buona ragione per farlo. Non è usato in modo abbastanza coerente per essere significativo.

Per rendere utile la convenzione, devi prima sapere che la funzione chiamata segue la convenzione. Quindi devi testare esplicitamente il valore restituito e decidere cosa fare. Se diventi indefinito , puoi presumere che si sia verificato un qualche tipo di errore di cui la funzione chiamata era a conoscenza . Ma se si è verificato un errore e la funzione lo sapeva ed è utile inviarlo a un ambiente più ampio, perché non utilizzare un oggetto errore? cioè lanciare un errore?

Quindi, in fin dei conti, la convenzione è praticamente inutile in qualcosa di diverso da programmi molto piccoli in ambienti semplici.


3

Una proprietà utile in null che undefined non si qualifica:

> null + 3
3
> undefined + 3
NaN

Uso nullquando voglio "disattivare" un valore numerico o inizializzarne alcuni. Il mio ultimo utilizzo è stato manipolare la trasformazione CSS:

const transforms = { perspective : null, rotateX : null };
// if already set, increase, if not, set to x
runTimeFunction((x) => { trasforms.perspective += x; });
// still useful, as setting perspective to 0 is different than turning it off
runTimeFunction2((x) => { transforms.perspective = null; });

// toCss will check for 'null' values and not set then at all
runTimeFunction3(() => { el.style.transform = toCss(transforms); });

Non sono sicuro se dovrei usare questa proprietà pensato ...


2

I nodi e gli elementi DOM non sono undefined, ma possono essere nulli.

  • Il nextSibling dell'ultimo figlio di un elemento è nullo.

  • Il precedente fratello del primo figlio è nullo.

  • Un riferimento document.getElementById è nullo se l'elemento non esiste nel documento.

Ma in nessuno di questi casi il valore è indefinito ; semplicemente non c'è nessun nodo lì.


Grazie per la spiegazione. Per me questo non potrebbe essere più controintuitivo.
tomekwi

Dipende davvero da cosa stai cercando di controllare. Ad esempio, se desideri vedere se esiste una variabile globale denominata "myVar", window.myVarrestituirà "undefined" se non esiste. Ci sono tonnellate di cose che restituiscono "indefinito" in JavaScript, solo ci sono tonnellate di cose che restituiscono "null" - tutto dipende dal contesto.
Thdoan

2

Alcuni hanno detto che va bene inizializzare gli oggetti su null. Volevo solo sottolineare che i valori predefiniti degli argomenti di destrutturazione non funzionano con null. Per esempio:

const test = ({ name } = {}) => {
  console.log(name)
}

test() // logs undefined
test(null) // throws error

Ciò richiede l'esecuzione di nullcontrolli prima di chiamare la funzione che può accadere spesso.


1

Sto elaborando questa domanda esatta in questo momento e osservando la seguente filosofia:

  1. Qualsiasi funzione destinata a restituire un risultato dovrebbe restituire null se non riesce a trovare un risultato
  2. Qualsiasi funzione che NON ha lo scopo di restituire un risultato restituisce implicitamente undefined.

Per me, questa domanda è significativa perché chiunque chiami una funzione che restituisce un risultato non dovrebbe avere dubbi sull'opportunità di testare undefined o null.

Questa risposta non cerca di affrontare:

  1. Valori di proprietà di null vs undefined
  2. Le variabili all'interno delle tue funzioni sono nulle e non definite

A mio parere, le variabili sono affari tuoi e non fanno parte della tua API, e le proprietà in qualsiasi sistema OO sono definite e quindi dovrebbero essere definite con un valore diverso da quello che sarebbero se non fossero definite (null per definito, undefined è ciò che tu ottenere quando si accede a qualcosa che non è nel tuo oggetto).


1

Ecco un motivo: var undefined = 1 è javascript legale, ma var null = 1è un errore di sintassi. La differenza è che nullè una parola chiave della lingua, mentre undefinedper qualche motivo non lo è.

Se il tuo codice si basa su confronti undefinedcome se fosse una parola chiave ( if (foo == undefined)- un errore molto facile da fare), funziona solo perché nessuno ha definito una variabile con quel nome. Tutto quel codice è vulnerabile a qualcuno che accidentalmente o intenzionalmente definisce una variabile globale con quel nome. Naturalmente, sappiamo tutti che la definizione accidentale di una variabile globale è totalmente impossibile in javascript ...


1
Usa void 0invece di indefinito.
Frederik Krautwald

1

Voglio solo aggiungere che con l'utilizzo di alcune librerie javascript, null e undefined possono avere conseguenze indesiderate.

Ad esempio, la getfunzione di lodash , che accetta un valore predefinito come terzo argomento:

const user = {
  address: {
    block: null,
    unit: undefined,
  }
}
console.log(_.get(user, 'address.block', 'Default Value')) // prints null
console.log(_.get(user, 'address.unit', 'Default Value')) // prints 'Default Value'
console.log(_.get(user, 'address.postalCode', 'Default Value')) // prints 'Default Value'

Un altro esempio: se usi defaultProps in React, se viene passata una proprietà null, gli oggetti di scena predefiniti non vengono usati perché null viene interpretato come un valore definito . per esempio

class MyComponent extends React.Component {
   static defaultProps = {
      callback: () => {console.log('COMPONENT MOUNTED')},
   }
   componentDidMount() {
      this.props.callback();
   }
}
//in some other component
<MyComponent />   // Console WILL print "COMPONENT MOUNTED"
<MyComponent callback={null}/>   // Console will NOT print "COMPONENT MOUNTED"
<MyComponent callback={undefined}/>   // Console WILL print "COMPONENT MOUNTED"

0

Sono completamente in disaccordo sul fatto che l'utilizzo null o undefined non sia necessario. indefinito è cosa che mantiene vivo l'intero processo di concatenamento del prototipo. Quindi il compilatore solo con null non può verificare se questa proprietà è uguale a null o non è definita nel prototipo dell'endpoint. In altri linguaggi tipizzati dinamici (ad esempio Python) genera un'eccezione se si desidera accedere a proprietà non definite, ma per i linguaggi basati su prototipi il compilatore dovrebbe anche controllare i prototipi genitore e qui ci sono il posto in cui undefined ha più bisogno.

L'intero significato dell'uso di null è semplicemente legare una variabile o una proprietà con un oggetto che è singleton e ha un significato di vuoto, e anche l'uso di null ha scopi di prestazione. Questi 2 codici hanno tempi di esecuzione diversi.

var p1 = function(){this.value = 1};
var big_array = new Array(100000000).fill(1).map((x, index)=>{
    p = new p1();
    if(index > 50000000){
       p.x = "some_string";
    }

    return p;
});
big_array.reduce((sum, p)=> sum + p.value, 0)

var p2 = function(){this.value = 1, p.x = null};
var big_array = new Array(100000000).fill(1).map((x, index)=>{
    p = new p2();
    if(index > 50000000){
       p.x = "some_string";
    }

    return p; 
});
big_array.reduce((sum, p)=> sum + p.value, 0)

0

Variabile sconosciuta: undefined.

Variabile conosciuta ancora alcun valore: null.

  1. Si riceve un oggetto da un server, server_object.
  2. Fai riferimento server_object.errj. Ti dice che è undefined. Ciò significa che non sa cosa sia.
  3. Ora fai riferimento server_object.err. Ti dice che è null. Ciò significa che stai facendo riferimento a una variabile corretta ma è vuota; quindi nessun errore.

Il problema è quando dichiari un nome di variabile senza un valore ( var hello) js lo dichiara come undefinedsegue: questa variabile non esiste; mentre i programmatori per lo più intendono: "Non gli ho ancora dato un valore", la definizione di null.

Quindi il comportamento predefinito di un programmatore - dichiarare una variabile senza valore come nulla - è in contrasto con js - dichiararla come non esistente. Inoltre, !undefinede !nullsono entrambi truecosì la maggior parte dei programmatori li tratta come equivalenti.

Ovviamente potresti assicurarti di farlo sempre, var hello = nullma la maggior parte non sporcherà il proprio codice in quanto tale per garantire la correttezza del tipo in un linguaggio volutamente sciolto, quando loro e l' !operatore trattano entrambi undefinede nullcome equivalenti.

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.