Javascript setzt eine Variable, wenn sie nicht definiert ist

172

Ich weiß, dass ich auf eine Javascript-Variable testen und sie dann definieren kann, wenn sie nicht definiert ist, aber es gibt keine Möglichkeit zu sagen

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

scheint ein viel klarerer Weg zu sein, und ich bin mir ziemlich sicher, dass ich das in anderen Sprachen gesehen habe.

Pedalpete
quelle
30
Das ist kein Test für "undefiniert", es ist ein Test für "Falsey"
Alnitak
3
Beachten Sie, dass localStorage.getItem()eine Ausnahme try...catch
ausgelöst
1
Mögliches Duplikat von Was bedeutet das Konstrukt x = x || y meine?
Michał Perłakowski

Antworten:

304

Ja, das kann es, aber genau genommen wird der Standardwert zugewiesen , wenn der abgerufene Wert falsch ist , im Gegensatz zu wirklich undefiniert . Es wäre daher nicht nur entsprechen , undefinedsondern auch null, false, 0, NaN, "" (aber nicht "0" ).

Wenn Sie nur dann die Standardeinstellung festlegen möchten, wenn die Variable streng undefinedist, schreiben Sie am sichersten:

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

In neueren Browsern ist es tatsächlich sicher zu schreiben:

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

Beachten Sie jedoch, dass dies in älteren Browsern möglich ist, in denen eine Variable undefinedmit einem definierten Wert deklariert werden durfte, wodurch der Test fehlschlug.

Alnitak
quelle
3
Ich bin überrascht, dass dieses Muster nicht in weiteren JS-Bibliotheken enthalten ist.
Joemaller
Gibt es einen Nachteil bei der Verwendung var x = (x === undefined ? def_val : x);als etwas länger var x = (typeof x === 'undefined') ? def_val : x;. Unterscheidet sich das Verhalten?
Marco Pashkov
3
@marco In älteren Browsern konnte undefinedeine Neudefinition durchgeführt werden, wodurch der Gleichheitstest fehlschlug.
Alnitak
@Alnitak Was ist der beste Ansatz, um eine ähnliche Syntax wie die von OP zu verwenden und trotzdem auf undefiniert zu prüfen?
Ivo Pereira
@IvoPereira Sie können den ||Ansatz nicht in einem strengen Test für undefiniert verwenden, Sie müssen einen expliziten Test für undefinedmit einer Bedingung verwenden.
Alnitak
26

Die ES6-Antwort für 2018 lautet :

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

Wenn die Variable x undefiniert ist, geben Sie die Variable y zurück. Wenn die Variable x definiert ist, geben Sie die Variable x zurück.

Sterling Bourne
quelle
4
Soweit ich das beurteilen kann, Object.isist es nicht besser als ===in diesem Fall. "Der Operator === (und auch der Operator ==) behandelt die Zahlenwerte -0 und +0 als gleich und Number.NaN als ungleich NaN." ( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ) Hier spielt es keine Rolle.
Trevor Dixon
5
Ich bin nicht einverstanden. Kennen Sie beide und verwenden Sie die entsprechende. Verwenden Sie Object.isdiese Option insbesondere, wenn beide Operanden möglicherweise vorhanden sind NaN.
Trevor Dixon
2
Wenn Object.is () in 100% der Anwendungsfälle und === in 98% der Anwendungsfälle funktioniert, warum würden Sie das Risiko eingehen, === überhaupt zu verwenden? Zum Beispiel: console.log (+0 === -0); // gibt true aus, während console.log (Object.is (+0, -0)); // gibt false aus - was ist besser? Ist negative 0 gleich positive 0? Das ist die Frage, die Sie sich stellen müssen, aber wenn Sie Object.is () verwenden, kennen Sie immer die Antwort. Sie sind nicht gleich, daher ist eine Ausgabe von false das richtige und erwartete Ergebnis.
Sterling Bourne
2
Der besondere Kontext hier ist immer vergleichbar mit undefined. Funktioniert also ===100% der Zeit, nicht nur 98%. Der Vorteil, ===dass es leichter zu lesen ist, insbesondere auf einen Blick, kürzer und ein unnötiger Methodenaufruf vermieden wird. Persönlich würde ich nur verwenden, Object.is()wenn die Situation es erfordert und ===in allen anderen Fällen bevorzugen .
Blubberdiblub
1
Absolut; wenn Sie ein erfahrener Programmierer sind. Wenn Sie nicht versehentlich ein Gleichheitszeichen vergessen, würde ich es keinem Entwickler wünschen, zu debuggen, warum == nicht irgendwo funktioniert. Besser sicher als leid und immer Object.is () verwenden. Der Grund, der in der Spezifikation enthalten war, war speziell, Entwicklern zu helfen, weniger fehlerhaften Code zu schreiben.
Sterling Bourne
7

Ich musste an mehreren Stellen "eine Variable setzen, wenn sie nicht definiert ist". Ich habe eine Funktion mit der Antwort von @Alnitak erstellt. Hoffentlich hilft es jemandem.

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

Verwendung:

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

Es scheint logischer zu überprüfen, typeofanstatt undefined? Ich gehe davon aus, dass Sie eine Zahl erwarten, 0wenn Sie die Variable auf undefiniert setzen:

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

In diesem Fall getVariablewird setVariable auf gesetzt, wenn es sich nicht um eine Zahl (Zeichenfolge, Objekt, was auch immer) handelt0

Bruno
quelle
5

ES2020 Antwort

Mit dem Nullish Coalescing Operator können Sie einen Standardwert festlegen , wenn dieser valuenull oder undefiniert ist.

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

Beachten Sie jedoch, dass der nullish coalescing-Operator den Standardwert für andere Arten von Falschwerten wie 0und nicht zurückgibt ''.

Beachten Sie, dass die Browserunterstützung für den Bediener begrenzt ist. Nach Angaben von caniuse werden nur 48,34% der Browser unterstützt (Stand April 2020). Die Unterstützung von Node.j wurde in Version 14 hinzugefügt .

gojun
quelle
2

Wenn Sie ein FP- Fan ( Functional Programming ) sind, hat Ramda eine nette Hilfsfunktion für diese Funktion namens defaultTo :

Verwendung:

const result = defaultTo(30)(value)

Es ist nützlicher, wenn es um undefinedboolesche Werte geht:

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

Damian Green
quelle
1
Dies ist genau const result = value || 30;, außer dass eine Zwischenfunktion und +1000 Bytes lib verwendet werden
Adelin
1
@Adelin nicht wahr, es behandelt auch Falschheit für boolesche Typen. Wenn Sie diese Bibliothek bereits verwenden (so wie ich), dann ist sie ziemlich nützlich und knapp
Damian Green
1

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

Zikes
quelle
Wird auch nicht 0 zuweisen, wenn localStorage.getItem('value'))zurückkehrtfalse
Karl Adler
1

Ich bin auch heute auf dieses Szenario gestoßen, in dem ich nicht wollte, dass Null für mehrere Werte überschrieben wird. Wir haben eine Datei mit einigen gängigen Dienstprogrammmethoden für solche Szenarien. Folgendes habe ich hinzugefügt, um das Szenario zu handhaben und flexibel zu sein.

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

Es kann dann aufgerufen werden, wobei die letzten beiden Parameter optional sind, wenn ich nur undefinierte Werte festlegen oder auch Null- oder 0-Werte überschreiben möchte. Hier ist ein Beispiel für einen Aufruf, bei dem die ID auf -1 gesetzt wird, wenn die ID undefiniert oder null ist, ein 0-Wert jedoch nicht überschrieben wird.

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

In unseren Tagen können Sie Ihren Ansatz tatsächlich mit JS machen:

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

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

console.log(x); // default value

Ihr Beispiel wird also funktionieren:

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

Funktioniert auch, wenn der Standardwert ein boolescher Wert ist:

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

Es scheint mir, dass für aktuelle Javascript-Implementierungen,

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

ist eine gute Möglichkeit, dies zu tun (mithilfe der Objektdekonstruktion).

TS
quelle
0

Logische Nullzuweisung, ES2020 + -Lösung

Neue Betreiber werden derzeit in den Browsern hinzugefügt werden, ??=, ||=, und &&=. Dieser Beitrag wird sich auf konzentrieren ??=.

Dies prüft, ob die linke Seite undefiniert oder null ist, und schließt kurz, falls bereits definiert. Wenn nicht, wird die rechte Seite der linken Variablen zugewiesen.

Methoden vergleichen

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

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

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

Grundlegende Beispiele

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

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

// Equivalent to
a = a ?? true

Objekt- / Array-Beispiele

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

?? = Browser-Unterstützung Juli 2020 - .03%

?? = Mozilla-Dokumentation

|| = Mozilla-Dokumentation

&& = Mozilla-Dokumentation

Gibolt
quelle
Ist es wirklich eine gute Idee, diese Antwort auf zwei andere Fragen zu kopieren ( Ersetzen Sie einen Wert, wenn er in JavaScript null oder undefiniert ist, und gibt es in JavaScript einen "Null-Koaleszenz" -Operator? )? Wäre es nicht besser, VTC als Duplikat oder Link zu verwandten Fragen in den Kommentaren zu verwenden?
user4642212
Die Fragen sind alle etwas unterschiedlich; als solche sind auch die Antworten. Die Beispiele sind konsistent, um den Inline-Kontext auf einen Blick zu verbessern. Wahrscheinlich hätte es für mehr Details verlinkt werden können, hätte aber einen zusätzlichen Hop benötigt, der dazu führen könnte, dass Leute die Lösung überspringen
Gibolt