javascript définit une variable si non définie

172

Je sais que je peux tester une variable javascript, puis la définir si elle n'est pas définie, mais n'y a-t-il pas un moyen de dire

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

semble être une manière beaucoup plus claire, et je suis à peu près sûr que j'ai vu cela dans d'autres langues.

pédale
la source
30
ce n'est pas un test pour "undefined", c'est un test pour "falsey"
Alnitak
3
Notez que localStorage.getItem()cela lèvera une exception si l'utilisateur a désactivé les cookies (au moins dans Chrome), vous voudrez peut-être l'envelopper dans une try...catchclause
urish
1
Double possible de Qu'est-ce que la construction x = x || tu veux dire?
Michał Perłakowski

Réponses:

304

Oui, il peut le faire, mais à proprement parler, cela attribuera la valeur par défaut si la valeur récupérée est false , par opposition à vraiment indéfinie . Il serait donc correspondre non seulement , undefinedmais aussi null, false, 0, NaN, "" (mais pas "0" ).

Si vous souhaitez définir la valeur par défaut uniquement si la variable est strictement, undefinedle moyen le plus sûr est d'écrire:

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

Sur les navigateurs plus récents, il est en fait sûr d'écrire:

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

mais sachez qu'il est possible de renverser cela sur les navigateurs plus anciens où il était permis de déclarer une variable nommée undefinedqui a une valeur définie, provoquant l'échec du test.

Alnitak
la source
3
Je suis surpris que ce modèle ne soit pas inclus dans plus de bibliothèques JS.
joemaller
y a-t-il un inconvénient à utiliser var x = (x === undefined ? def_val : x);comme légèrement plus long var x = (typeof x === 'undefined') ? def_val : x;. Le comportement diffère-t-il?
Marco Pashkov
3
@marco dans les navigateurs plus anciens, il était possible undefinedd'être redéfini, ce qui a fait échouer le test d'égalité.
Alnitak
@Alnitak quelle est la meilleure approche pour utiliser une syntaxe similaire à celle qu'OP utilise et toujours vérifier si elle n'est pas définie?
Ivo Pereira
@IvoPereira Vous ne pouvez pas utiliser l' ||approche dans un test strict pour undefined, vous devez utiliser un test explicite pour undefinedavec un conditionnel.
Alnitak
26

La réponse ES6 2018 est :

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

Si la variable x n'est pas définie, renvoie la variable y ... sinon si la variable x est définie, renvoie la variable x.

Sterling Bourne
la source
4
Pour autant que je sache, ce Object.isn'est pas mieux que ===dans ce cas. "L'opérateur === (et l'opérateur == également) traite les valeurs numériques -0 et +0 comme égales et traite Number.NaN comme différent de NaN." ( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ) Cela n'a pas d'importance ici.
Trevor Dixon
5
Je ne suis pas d'accord. Connaissez-les tous les deux et utilisez celui qui convient. En particulier, utilisez Object.issi les deux opérandes peuvent être NaN.
Trevor Dixon
2
Si Object.is () fonctionne sur 100% des cas d'utilisation, et === fonctionne sur 98% des cas d'utilisation, pourquoi risqueriez-vous d'utiliser === du tout? Par exemple: console.log (+0 === -0); // renvoie true, tandis que console.log (Object.is (+0, -0)); // renvoie false - quel est le meilleur? Le 0 négatif est-il le même que le 0 positif? C'est la question que vous devez vous poser, mais si vous utilisez Object.is (), vous connaissez toujours la réponse. Ils ne sont pas les mêmes, donc une sortie de false est le résultat correct et attendu.
Sterling Bourne
2
Le contexte particulier ici se compare toujours à undefined. Cela ===fonctionnera donc 100% du temps, pas seulement 98%. L'avantage d' ===être il est plus facile à lire, surtout en un coup d'œil, plus court et évite un appel de méthode inutile. Personnellement, je n'utiliserais que Object.is()lorsque la situation l'exige et préférerais ===dans tous les autres cas.
blubberdiblub
1
Absolument; si vous êtes un codeur expérimenté. Sauf si vous oubliez accidentellement un signe égal, auquel cas le débogage pourquoi == ne fonctionne pas quelque part est quelque chose que je ne souhaiterais jamais à aucun développeur. Mieux vaut prévenir que guérir et utilisez toujours Object.is (), la raison pour laquelle a été inclus dans la spécification était spécifiquement pour aider les développeurs à écrire moins de code bogué.
Sterling Bourne
7

J'avais besoin de "définir une variable si non définie" à plusieurs endroits. J'ai créé une fonction en utilisant la réponse @Alnitak. Espérons que cela aide quelqu'un.

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

Usage:

hasPoints = setDefaultVal(this.hasPoints, true);
Mcestone
la source
6

Il semble plus logique de vérifier typeofau lieu de undefined? Je suppose que vous attendez un nombre lorsque vous définissez le var 0lorsqu'il n'est pas défini:

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

Dans ce cas, si ce getVariablen'est pas un nombre (chaîne, objet, peu importe), setVariable est défini sur0

Bruno
la source
5

Réponse ES2020

Avec l' opérateur de coalescence Nullish , vous pouvez définir une valeur par défaut si elle valueest nulle ou non définie.

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

Cependant, vous devez être conscient que l'opérateur de fusion nullish ne renvoie pas la valeur par défaut pour les autres types de valeurs fausses telles que 0et ''.

Veuillez noter que la prise en charge du navigateur pour l'opérateur est limitée. Selon les données de caniuse , seuls 48,34% des navigateurs sont pris en charge (en avril 2020). La prise en charge de Node.js a été ajoutée dans la version 14 .

gojun
la source
2

Si vous êtes un fan FP ( programmation fonctionnelle ), Ramda a une fonction d'aide soignée pour cela appelée defaultTo :

usage:

const result = defaultTo(30)(value)

C'est plus utile lorsqu'il s'agit de undefinedvaleurs booléennes:

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

Damian Green
la source
1
c'est exactement const result = value || 30;, sauf si vous utilisez une fonction intermédiaire et +1000 octets lib
Adelin
1
@Adelin n'est pas vrai, il gère également le faux pour les types booléens. Si vous utilisez déjà cette bibliothèque (comme je le suis), alors c'est assez utile et laconique
Damian Green
1

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

Zikes
la source
N'attribuera pas également 0 si localStorage.getItem('value'))retournefalse
Karl Adler
1

Je suis également entré dans ce scénario aujourd'hui où je ne voulais pas que zéro soit écrasé pour plusieurs valeurs. Nous avons un fichier avec des méthodes utilitaires courantes pour des scénarios comme celui-ci. Voici ce que j'ai ajouté pour gérer le scénario et être flexible.

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;
    }
}

Il peut ensuite être appelé avec les deux derniers paramètres facultatifs si je veux définir uniquement des valeurs non définies ou également écraser les valeurs nulles ou 0. Voici un exemple d'appel à celui-ci qui définira l'ID sur -1 si l'ID est indéfini ou nul, mais ne remplacera pas une valeur 0.

data.ID = Util.getIfNotSet(data.ID, -1, true);
Mark Seefeldt
la source
1

De nos jours, vous pouvez réellement faire votre approche avec JS:

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

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

console.log(x); // default value

Donc, votre exemple fonctionnera:

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

Fonctionne même si la valeur par défaut est une valeur booléenne:

var setVariable = ( (b = 0) => b )( localStorage.getItem('value') );
Tsz Lam Yau
la source
0

Il me semble que pour les implémentations javascript actuelles,

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

est une bonne façon de faire cela (en utilisant la déconstruction d'objets).

TS
la source
0

Affectation logique nulle, solution ES2020 +

De nouveaux opérateurs sont actuellement ajoutés aux navigateurs, ??=, ||=, et &&=. Cet article se concentrera sur ??=.

Ceci vérifie si le côté gauche est indéfini ou nul, court-circuitant s'il est déjà défini. Sinon, le côté droit est affecté à la variable du côté gauche.

Comparaison des méthodes

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

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

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

Exemples de base

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

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

// Equivalent to
a = a ?? true

Exemples d'objets / de tableaux

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" }

?? = Support du navigateur juillet 2020 - .03%

?? = Documentation Mozilla

|| = Documentation Mozilla

&& = Documentation Mozilla

Gibolt
la source
Est-ce vraiment une bonne idée de copier cette réponse à deux autres questions ( Remplacer une valeur si nulle ou indéfinie en JavaScript et Y a - t-il un opérateur "null coalescing" en JavaScript? )? Ne serait-il pas préférable de VTC en double ou en lien avec des questions connexes dans les commentaires?
user4642212
Les questions sont toutes légèrement différentes; en tant que telles sont les réponses. Les exemples sont cohérents pour améliorer le contexte en ligne en un coup d'œil. Aurait probablement pu établir un lien pour plus de détails, mais aurait nécessité un saut supplémentaire qui pourrait amener les gens à ignorer la solution
Gibolt