Esiste un operatore “null coalescing” in JavaScript?

Esiste un operatore null coalescente in Javascript?

Ad esempio, in C #, posso farlo:

String someString = null; var whatIWant = someString ?? "Cookies!"; 

La migliore approssimazione che riesco a capire per Javascript sta usando l’operatore condizionale:

 var someString = null; var whatIWant = someString ? someString : 'Cookies!'; 

Che è sorta icky IMHO. Posso fare di meglio?

L’equivalente JavaScript dell’operatore null coalescente C # ( ?? ) utilizza un OR logico ( || ):

 var whatIWant = someString || "Cookies!"; 

Ci sono casi (chiariti di seguito) che il comportamento non corrisponde a quello di C #, ma questo è il modo generale e conciso di assegnare valori predefiniti / alternativi in ​​JavaScript.


Una precisazione

Indipendentemente dal tipo del primo operando, se il cast di un booleano risulta false , l’assegnazione utilizzerà il secondo operando. Attenzione a tutti i casi seguenti:

 alert(Boolean(null)); // false alert(Boolean(undefined)); // false alert(Boolean(0)); // false alert(Boolean("")); // false alert(Boolean("false")); // true -- gotcha! :) 

Questo significa:

 var whatIWant = null || new ShinyObject(); // is a new shiny object var whatIWant = undefined || "well defined"; // is "well defined" var whatIWant = 0 || 42; // is 42 var whatIWant = "" || "a million bucks"; // is "a million bucks" var whatIWant = "false" || "no way"; // is "false" 
 function coalesce() { var len = arguments.length; for (var i=0; i 

questa soluzione funziona come la funzione di coalesce SQL, accetta qualsiasi numero di argomenti e restituisce null se nessuno di essi ha un valore. Si comporta come il C # ?? operatore nel senso che "", false e 0 sono considerati NOT NULL e quindi contano come valori effettivi. Se provieni da uno sfondo .net, questa sarà la soluzione più naturale.

Se || come una sostituzione di C # ?? non è abbastanza buono nel tuo caso, perché inghiotte stringhe e zeri vuoti, puoi sempre scrivere la tua funzione:

  function $N(value, ifnull) { if (value === null || value === undefined) return ifnull; return value; } var whatIWant = $N(someString, 'Cookies!'); 

Nessuno ha menzionato qui il potenziale di NaN , che – per me – è anche un valore nullo. Quindi, ho pensato di aggiungere il mio due centesimi.

Per il codice indicato:

 var a, b = null, c = parseInt('Not a number'), d = 0, e = '', f = 1 ; 

Se dovessi usare il || operatore, ottieni il primo valore non falso:

 var result = a || b || c || d || e || f; // result === 1 

Se usi il tipico metodo di coalescenza, come postato qui , otterrai c , che ha il valore: NaN

 var result = coalesce(a,b,c,d,e,f); // result.toString() === 'NaN' 

Nessuno di questi sembra giusto per me. Nel mio piccolo mondo di logica di coalizione, che potrebbe differire dal vostro mondo, considero indefinito, nullo e NaN come tutti “null-ish”. Quindi, mi aspetterei di ottenere d (zero) dal metodo di coalesce.

Se il cervello di qualcuno funziona come il mio e vuoi escludere NaN , allora questo metodo compirà questo:

 function coalesce() { var i, undefined, arg; for( i=0; i < arguments.length; i++ ) { arg = arguments[i]; if( arg !== null && arg !== undefined && (typeof arg !== 'number' || arg.toString() !== 'NaN') ) { return arg; } } return null; } 

Per chi vuole che il codice sia il più breve ansible e non si preoccupi di una mancanza di chiarezza, è ansible utilizzarlo come suggerito da @impinball. Questo sfrutta il fatto che NaN non è mai uguale a NaN. Puoi leggere di più su questo qui: perché NaN non è uguale a NaN?

 function coalesce() { var i, arg; for( i=0; i < arguments.length; i++ ) { arg = arguments[i]; if( arg != null && arg === arg ) { //arg === arg is false for NaN return arg; } } return null; } 

Sì, arriverà presto. Vedi la proposta qui e lo stato di implementazione qui .

Sembra questo:

 x ?? y 

Esempio

 const response = { settings: { nullValue: null, height: 400, animationDuration: 0, headerText: '', showSplashScreen: false } }; const undefinedValue = response.settings?.undefinedValue ?? 'some other default'; // result: 'some other default' const nullValue = response.settings?.nullValue ?? 'some other default'; // result: 'some other default' const headerText = response.settings?.headerText ?? 'Hello, world!'; // result: '' const animationDuration = response.settings?.animationDuration ?? 300; // result: 0 const showSplashScreen = response.settings?.showSplashScreen ?? true; // result: false 

Attualmente nessun supporto, ma il processo di standardizzazione JS sta lavorando su di esso: https://github.com/tc39/proposal-optional-chaining

fai attenzione alla specifica definizione di JavaScript di null. ci sono due definizioni per “nessun valore” in javascript. 1. Null: quando una variabile è null, significa che non contiene dati in essa, ma la variabile è già definita nel codice. come questo:

 var myEmptyValue = 1; myEmptyValue = null; if ( myEmptyValue === null ) { window.alert('it is null'); } // alerts 

in tal caso, il tipo di variabile è in realtà Oggetto. Provalo.

 window.alert(typeof myEmptyValue); // prints Object 
  1. Non definito: quando una variabile non è stata definita prima nel codice e come previsto, non contiene alcun valore. come questo:

     if ( myUndefinedValue === undefined ) { window.alert('it is undefined'); } // alerts 

se tale caso, il tipo della variabile è ‘indefinito’.

si noti che se si utilizza l’operatore di confronto per la conversione del tipo (==), JavaScript agirà allo stesso modo per entrambi questi valori vuoti. per distinguere tra loro, utilizzare sempre l’operatore di confronto rigoroso del tipo (===).

Dopo aver letto il tuo chiarimento, la risposta di @Ates Goral fornisce come eseguire la stessa operazione che stai facendo in C # in JavaScript.

@ La risposta di Gumbo fornisce il modo migliore per verificare la nullità; tuttavia, è importante notare la differenza in == rispetto a === in JavaScript, specialmente quando si tratta di problemi di controllo per undefined e / o null .

C’è un ottimo articolo sulla differenza in due termini qui . Fondamentalmente, capisci che se usi == invece di === , JavaScript proverà a fondere i valori che stai confrontando e restituirà il risultato del confronto dopo questa coalescenza.