Gibt es einen bekannten Grund, warum ich vorbeikomme? null
als Parameter in ES6 verwendet nicht den Standardparameter, wenn einer bereitgestellt wird?
function sayHello(name = "World") {
console.log("Hello, " + name + "!");
}
sayHello("Jim"); // Hello, Jim!
sayHello(undefined); // Hello, World!
sayHello(null); // Hello, null!
Das ist nicht so offensichtlich
Ich habe einige Kommentare gelesen, warum undefined
ist ganz anders als null
und deshalb erklärt es das aktuelle Verhalten von Standardparametern.
Man könnte argumentieren, dass explizit undefiniert übergeben wird sollte nicht Auslösen der Standardwertsubstitution, denn wenn ich eine Funktion habe:
const f = (x = 'default') => console.log(x);
Ich möchte es drucken "default"
wenn ich es ausführe als:
f();
aber ich möchte es drucken "undefined"
wenn ich es explizit ausführe als:
f(undefined);
denn warum sollte ich sonst verwenden f(undefined)
an erster Stelle? Meine Absicht ist hier eindeutig, ein Argument zu liefern, anstatt es wegzulassen.
Beispiele dagegen
Betrachten Sie nun diese Funktion:
const g = (...a) => console.log(JSON.stringify(a));
Wenn ich es verwende als:
g();
Ich bekomme: []
Aber wenn ich es verwende als:
g(undefined);
Ich bekomme: [null]
was deutlich zeigt, dass:
- Vorbeigehen
undefined
ist nicht das gleiche als überhaupt kein Argument weiterzugeben
- manchmal
null
kann sein ein Standardwert statt undefined
TC39-Entscheidung
Einige Hintergrundinformationen zum aktuellen Verhalten der Standardparameter finden Sie in den Sitzungsnotizen von TC39 vom 24. Juli 2012:
Übrigens zeigt es das ausdrücklich vorbei undefined
ursprünglich nicht den Standardwert im ersten Entwurf auslösen und es gab eine Diskussion darüber, ob es das tun sollte oder nicht. Wie Sie also sehen können, war das aktuelle Verhalten für die TC39-Mitglieder nicht so offensichtlich, wie es jetzt für Leute zu sein scheint, die hier kommentieren.
Andere Sprachen
Allerdings ist die Entscheidung, was die Defaultwertsubstitution auslösen soll und was nicht, letztlich völlig willkürlich. Sogar mit einem separaten undefined
und null
kann aber ziemlich seltsam sein, wenn man darüber nachdenkt. Einige Sprachen haben nur undefined
(wie undef
in Perl), manche haben nur null
(wie Java) verwenden einige Sprachen Entsprechungen von false
oder eine leere Liste oder ein Array dafür (wie Schema, wo Sie eine leere Liste haben können oder #f
(falsch), aber es gibt kein Äquivalent von null
das würde sich sowohl von einer leeren Liste als auch von einem falschen Wert unterscheiden) und einige Sprachen haben nicht einmal Äquivalente von null
, false
oder undefined
(wie C, das statt Ganzzahlen verwendet true
und false
und einen NULL-Zeiger, der eigentlich ein normaler Zeiger ist, der auf die Adresse 0 zeigt – wodurch diese Adresse unzugänglich wird, selbst wenn sie von einem Code zugeordnet wird, der auf Null-Zeiger testet).
Was du tun kannst
Jetzt kann ich verstehen, dass Sie Standardwerte für ersetzen müssen null
. Leider ist dies kein Standardverhalten, aber Sie können eine einfache Funktion erstellen, die Ihnen hilft:
const N = f => (...a) => f(...a.map(v => (v === null ? undefined : v)));
Jetzt jedes Mal, wenn Sie Standardeinstellungen ersetzen möchten null
Werte können Sie es so verwenden. ZB wenn Sie diese Funktion aus einem der obigen Beispiele haben:
const f = (x = 'default') => console.log(x);
es wird gedruckt "default"
zum f()
und f(undefined)
aber nicht für f(null)
. Aber wenn Sie die verwenden N
oben definierte Funktion zum Definieren der f
funktionieren so:
const f = N((x = 'default') => console.log(x));
jetzt f()
und f(undefined)
aber auch f(null)
Drucke "default"
.
Wenn Sie ein etwas anderes Verhalten wünschen, z. B. das Ersetzen von Standardwerten für leere Zeichenfolgen – nützlich für Umgebungsvariablen, die manchmal auf leere Zeichenfolgen gesetzt werden können, anstatt nicht vorhanden zu sein, können Sie Folgendes verwenden:
const N = f => (...a) => f(...a.map(v => (v === '' ? undefined : v)));
Wenn Sie möchten, dass alle falschen Werte ersetzt werden, können Sie es wie folgt verwenden:
const N = f => (...a) => f(...a.map(v => (v || undefined)));
Wenn Sie möchten, dass leere Objekte ersetzt werden, können Sie Folgendes verwenden:
const N = f => (...a) => f(...a.map(v => (Object.keys(v).length ? v : undefined)));
usw…
Fazit
Der Punkt ist, dass es Ihr Code ist und Sie wissen, was die API Ihrer Funktionen sein sollte und wie die Standardwerte funktionieren sollten. Glücklicherweise ist JavaScript leistungsfähig genug, damit Sie das, was Sie brauchen, mit etwas höherer Funktionsmagie leicht erreichen können (auch wenn dies sozusagen nicht das Standardverhalten von Standardwerten ist).
Genauso werden Standardparameter in der Spezifikation definiert. Sehen MDN: (Hervorhebung von mir)
Standardfunktionsparameter ermöglichen es, formale Parameter mit Standardwerten zu initialisieren, wenn kein Wert oder undefiniert ist bestanden.
null
ist weder kein Wertnoch undefined
sodass die Standardinitialisierung nicht ausgelöst wird.
null
ein Wert ist, der nicht den zu verwendenden Standardwert auslöst, werden die Standardwerte verwendet, wenn das Argument ist undefined
.
Ramdajs-Versionscode
// import ramda
// infra code
const isEmptyOrNil = (value) => isEmpty(value) || isNil(value)
const nullChange = (defaultValue) => (value) => isEmptyOrNil(value)? defaultValue: value
// single null
const _somef = (value) => value
const somefWithDefault = (defaultValue) => pipe(nullChange(defaultValue), _somef)
const somef = somefWithDefault('myValue')
somef(null)
// many args
const _somef2 = (value, value2, value3) => value + value2 + value3
const nullChangeMyValue = nullChange('myValue')
const somef2 = useWith(_somef2, [nullChangeMyValue, nullChangeMyValue, nullChangeMyValue])
somef2(null, undefined, 1234)
// many args2 version2
const nullChangeWith = (defaultValue) => nullChange(defaultValue)
const arrayNullChangeWith = (defaultValue) => (array) => array.map(nullChangeWith(defaultValue))
const arg2Array = (...args) => args
const funcApplyDefaultValue = (defaultValue) => (func) => pipe(
arg2Array, arrayNullChangeWith(defaultValue), apply(func)
)
const v2somef2 = funcApplyDefaultValue(8)(_somef2)
v2somef2(1,2,null)
gits: https://gist.github.com/otwm/3a6358e53ca794cc2e57ade4af91d3bb
weil null ein gültiger Wert ist?
– toskv
22. September 2015 um 19:14 Uhr
nein, ist es nicht 🙂 Sie können hier den Unterschied zwischen undefined und null lesen stackoverflow.com/questions/5076944/…
– toskv
22. September 2015 um 19:17 Uhr
@toskv Wenn
undefined
war nicht ein Wert, dann könnte es nicht zugewiesen werden, aber es kann sein. Dies ist der einfachste Test, um festzustellen, ob etwas ein Wert ist. Und ganz einfach, diese Antwort ist im Kontext falsch:undefined
wird als verwendet Standardwert in bestimmten Fällen; Dies ist nicht undefiniert machen ‘kein Wert’. In Betracht ziehen:a = new Array(1)
. Danna[0]
wird die ergebenundefined
Wert, obwohl0 in a
ist falsch. Dass es,a[0]
enthält ‘keinen Wert’, obwohl dies der Fall sein wird auswerten zum (Standard)undefined
Wert.– Benutzer2864740
22. September 2015 um 19:17 Uhr
@toskv Ich habe oben erklärt, warum das falsch ist. Apropos “wenn die Variable nicht definiert wurde” (im Fall von
typeof x === 'undefined'
wox
allein würde/könnte einen ReferenceError werfen) hat keinen Einfluss darauf, dassundefined
ist ein Wert. Insbesondere „undefined“ in JavaScript tut dies nicht bedeutet streng genommen „nicht definiert/deklariert“.– Benutzer2864740
22. September 2015 um 19:21 Uhr
Ich glaube, ich habe mich vorher schlecht ausgedrückt. Es ist nicht so, dass die Variable nicht definiert ist, in diesem Fall zeigt die Variable auf einen noch nicht definierten Wert. Während var x = null bedeutet, dass x den definierten Wert von null hat. Sie können sich undefined als nicht initialisiert vorstellen, während null ohne Wert initialisiert wird. Es ist verwirrend, ich weiß. @FelixKling
– toskv
23. September 2015 um 5:44 Uhr