javascript imposta una variabile se non definita


172

So che posso testare una variabile javascript e quindi definirla se non è definita, ma non c'è modo di dire

var setVariable = localStorage.getItem ('value') || 0;

sembra un modo molto più chiaro e sono abbastanza sicuro di averlo visto in altre lingue.


30
che non è un test per "indefinito", è un test per "falso"
Alnitak

3
Nota che localStorage.getItem()genererà un'eccezione se l'utente ha disabilitato i cookie (almeno in Chrome), quindi potresti volerlo racchiudere in una try...catchclausola
esorta

Risposte:


304

Sì, può farlo, ma a rigor di termini che assegnerà il valore predefinito se il valore recuperato è falso , al contrario di veramente indefinito . Sarebbe quindi non solo corrispondere undefined, ma anche null, false, 0, NaN, "" (ma non è "0" ).

Se si desidera impostare il valore predefinito solo se la variabile è rigorosamente, undefinedil modo più sicuro è scrivere:

var x = (typeof x === 'undefined') ? your_default_value : x;

Sui browser più recenti è effettivamente sicuro scrivere:

var x = (x === undefined) ? your_default_value : x;

ma tieni presente che è possibile sovvertirlo nei browser più vecchi in cui era consentito dichiarare una variabile denominata undefinedche ha un valore definito, causando il fallimento del test.


3
Sono sorpreso che questo schema non sia incluso in più librerie JS.
Joemaller,

c'è un aspetto negativo nell'usare var x = (x === undefined ? def_val : x);come leggermente più lungo var x = (typeof x === 'undefined') ? def_val : x;. Il comportamento differisce?
Marco Pashkov,

3
@marco nei browser più vecchi era possibile undefinedessere ridefinito, facendo fallire il test di uguaglianza.
Alnitak,

@Alnitak qual è l'approccio migliore per utilizzare una sintassi simile a quella utilizzata da OP e verificare ancora se non è definita?
Ivo Pereira,

@IvoPereira Non è possibile utilizzare l' ||approccio in un test rigoroso per indefinito, è necessario utilizzare un test esplicito per undefinedun condizionale.
Alnitak,

26

La risposta ES6 2018 è :

return Object.is(x, undefined) ? y : x;

Se la variabile x non è definita, restituisce la variabile y ... altrimenti, se viene definita la variabile x, restituisce la variabile x.


4
Per quanto ne so, Object.isnon è meglio che ===in questo caso. "L'operatore === (e anche l'operatore ==) considera i valori numerici -0 e +0 come uguali e tratta Number.NaN come non uguale a NaN." ( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ) Qui non importa.
Trevor Dixon,

5
Non sono d'accordo. Conoscerli entrambi e utilizzare quello appropriato. In particolare, utilizzare Object.isse entrambi gli operandi potrebbero essere NaN.
Trevor Dixon,

2
Se Object.is () funziona sul 100% dei casi d'uso e === funziona sul 98% dei casi d'uso, perché rischieresti di usare ===? Ad esempio: console.log (+0 === -0); // genera true, mentre console.log (Object.is (+0, -0)); // produce false - qual è la migliore? 0 negativo è uguale a 0 positivo? Questa è la domanda che ti devi porre, ma se usi Object.is (), conosci sempre la risposta. Non sono gli stessi, quindi un risultato falso è il risultato corretto e previsto.
Sterling Bourne,

2
Il contesto particolare qui viene sempre confrontato con undefined. Quindi ===funzionerà il 100% delle volte, non solo il 98%. Il vantaggio di ===essere è più facile da leggere, soprattutto a prima vista, più breve ed evita una chiamata di metodo non necessaria. Personalmente userei solo Object.is()quando la situazione lo richiede e preferirei ===in tutti gli altri casi.
blubberdiblub,

1
Assolutamente; se sei un programmatore esperto. A meno che tu non dimentichi accidentalmente un segno di uguale, nel qual caso il debug del motivo per cui == non funziona da qualche parte è qualcosa che non avrei mai desiderato per nessuno sviluppatore. Meglio prevenire che curare e usare sempre Object.is (), il motivo è stato incluso nelle specifiche è stato appositamente per aiutare gli sviluppatori a scrivere meno codice errato.
Sterling Bourne,

7

Avevo bisogno di "impostare una variabile se non definita" in diversi punti. Ho creato una funzione usando la risposta @Alnitak. Spero che aiuti qualcuno.

function setDefaultVal(value, defaultValue){
   return (value === undefined) ? defaultValue : value;
}  

Uso:

hasPoints = setDefaultVal(this.hasPoints, true);

6

Sembra più logico controllare typeofinvece di undefined? Presumo che ti aspetti un numero quando imposti il ​​var su 0quando non definito:

var getVariable = localStorage.getItem('value');
var setVariable = (typeof getVariable == 'number') ? getVariable : 0;

In questo caso, se getVariablenon è un numero (stringa, oggetto, qualunque cosa), setVariable è impostato su0


5

Risposta ES2020

Con l' operatore Nullish Coalescing , è possibile impostare un valore predefinito se valueè nullo o non definito.

const setVariable = localStorage.getItem('value') ?? 0;

Tuttavia, è necessario tenere presente che l'operatore di coalescenza nullish non restituisce il valore predefinito per altri tipi di valori falsi come 0e ''.

Si noti che il supporto del browser per l'operatore è limitato. Secondo i dati di caniuse , solo il 48,34% dei browser è supportato (ad aprile 2020). Il supporto Node.js è stato aggiunto nella versione 14 .


2

Se sei un fan di FP ( programmazione funzionale ), Ramda ha una funzione di aiuto ordinata per questo chiamato defaultTo :

utilizzo:

const result = defaultTo(30)(value)

È più utile quando si hanno a che fare con undefinedvalori booleani:

const result2 = defaultTo(false)(dashboard.someValue)


1
questo è esattamente const result = value || 30;, tranne per il fatto che sta usando una funzione intermedia e +1000 byte lib
Adelin il

1
@Adelin non è vero, gestisce anche i falsi per i tipi booleani. Se stai già usando questa lib (come lo sono io), allora è piuttosto utile e conciso
Damian Green

1

var setVariable = (typeof localStorage.getItem('value') !== 'undefined' && localStorage.getItem('value')) || 0;


Non assegnerà anche 0 se localStorage.getItem('value'))restituiscefalse
Karl Adler

1

Sono andato in questo scenario anche oggi, dove non volevo che zero venisse sovrascritto per diversi valori. Abbiamo un file con alcuni metodi di utilità comuni per scenari come questo. Ecco cosa ho aggiunto per gestire lo scenario ed essere flessibile.

function getIfNotSet(value, newValue, overwriteNull, overwriteZero) {
    if (typeof (value) === 'undefined') {
        return newValue;
    } else if (value === null && overwriteNull === true) {
        return newValue;
    } else if (value === 0 && overwriteZero === true) {
        return newValue;
    } else {
        return value;
    }
}

Può quindi essere chiamato con gli ultimi due parametri che sono facoltativi se voglio impostare solo per valori non definiti o anche sovrascrivere valori null o 0. Ecco un esempio di una chiamata che imposta l'ID su -1 se l'ID è indefinito o nullo, ma non sovrascriverà un valore 0.

data.ID = Util.getIfNotSet(data.ID, -1, true);

1

Ai nostri giorni puoi effettivamente fare il tuo approccio con JS:

// Your variable is null
// or '', 0, false, undefined
let x = null;

// Set default value
x = x || 'default value';

console.log(x); // default value

Quindi il tuo esempio funzionerà:

const setVariable = localStorage.getItem('value') || 0;

0

Funziona anche se il valore predefinito è un valore booleano:

var setVariable = ( (b = 0) => b )( localStorage.getItem('value') );

0

Mi sembra che per le attuali implementazioni javascript,

var [result='default']=[possiblyUndefinedValue]

è un bel modo per farlo (usando la decostruzione degli oggetti).


0

Assegnazione nullo logica, soluzione ES2020 +

I nuovi operatori sono attualmente in fase aggiunti ai browser, ??=, ||=, e &&=. Questo post si concentrerà su ??=.

Controlla se il lato sinistro è indefinito o nullo, corto circuito se già definito. In caso contrario, il lato destro è assegnato alla variabile del lato sinistro.

Metodi di confronto

// Using ??=
name ??= "Dave"

// Previously, ES2020
name = name ?? "Dave"

// Before that (not equivalent, but commonly used)
name = name || "Dave" // name ||= "Dave"

Esempi di base

let a          // undefined
let b = null
let c = false

a ??= true  // true
b ??= true  // true
c ??= true  // false

// Equivalent to
a = a ?? true

Esempi di oggetti / array

let x = ["foo"]
let y = { foo: "fizz" }

x[0] ??= "bar"  // "foo"
x[1] ??= "bar"  // "bar"

y.foo ??= "buzz"  // "fizz"
y.bar ??= "buzz"  // "buzz"

x  // Array [ "foo", "bar" ]
y  // Object { foo: "fizz", bar: "buzz" }

?? = Supporto browser luglio 2020 - .03%

?? = Documentazione di Mozilla

|| = Documentazione Mozilla

&& = Documentazione Mozilla


È davvero una buona idea copiare questa risposta in altre due domande ( Sostituire un valore se nullo o non definito in JavaScript e Esiste un operatore "null coalescing" in JavaScript? )? Non sarebbe meglio VTC come duplicato o collegamento a domande correlate nei commenti?
user4642212

Le domande sono tutte leggermente diverse; come tale, lo sono anche le risposte. Gli esempi sono coerenti per migliorare il contesto in linea a colpo d'occhio. Probabilmente avrebbe potuto collegarsi per maggiori dettagli, ma avrebbe richiesto un salto in più che potrebbe far saltare la soluzione alle persone
Gibolt,
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.