Warum funktioniert dies in einer Node.js
Konsole (getestet in 4.1.1 und 5.3.0), aber nicht im Browser (getestet in Chrome)? Dieser Codeblock sollte eine anonyme Funktion erstellen und aufrufen, die protokolliert Ok
.
() => {
console.log('Ok');
}()
Auch wenn das oben genannte in Node funktioniert , funktioniert dies nicht:
n => {
console.log('Ok');
}()
Noch dies:
(n) => {
console.log('Ok');
}()
Seltsam ist, dass der Parameter beim Hinzufügen tatsächlich einen SyntaxError
auf den sofort aufrufenden Teil auslöst.
(n => { console.log("Ok"); })();
?(n => { console.log("Ok"); })()
funktioniert sogar in der Chrome Dev ConsoleNode.js
der ersten Version nicht mehr funktioniert.Antworten:
Sie müssen es zu einem Funktionsausdruck anstelle einer Funktionsdefinition machen, die keinen Namen benötigt und es zu einem gültigen JavaScript macht.
Ist das Äquivalent von IIFE
Und der mögliche Grund, warum dies in Node.js, aber nicht in Chrome funktioniert, ist, dass sein Parser es als selbstausführende Funktion interpretiert
funktioniert gut in
Node.js
Dies ist ein Funktionsausdruck und Chrome und Firefox und die meisten Browser interpretieren es so. Sie müssen es manuell aufrufen.Die am weitesten verbreitete Methode, den Parser anzuweisen, einen Funktionsausdruck zu erwarten, besteht darin, ihn in Parens zu verpacken, da Parens in JavaScript keine Anweisungen enthalten können. Wenn der Parser auf das Funktionsschlüsselwort stößt, kann er es zu diesem Zeitpunkt als Funktionsausdruck und nicht als Funktionsdeklaration analysieren.
In Bezug auf die parametrisierte Version wird dies funktionieren.
quelle
Node.js
und protokolliert den Wert tatsächlich. Meine Frage ist, warum es funktioniert? Und warum nicht, wenn ich den Parameter hinzufüge?IIFE
s und weiß, wie ich meinen Code reparieren kann. Ich war nur neugierig, warum zum Beispiel meinIIFE
nicht funktioniert, wenn dern
Parameter hinzugefügt wird, obwohl es ohne den Parameter funktioniert.function(){}()
Pfeilfunktionen? Wenn ich möchte, dass das Funktionsobjekt exponierte Funktionsausdrücke davor schützt.Keines davon sollte ohne Klammern funktionieren.
Warum?
Denn laut Spezifikation:
Eine ArrowFunction kann sich also nicht auf der linken Seite einer CallExpression befinden .
Was dies bedeutet effektiv, wie
=>
interpretiert werden sollte, ist , dass es auf die gleiche Art von Niveau als Zuweisungsoperatoren arbeitet=
,+=
usw.Bedeutungx => {foo}()
nicht werden(x => {foo})()
x => ({foo}())
Der Interpreter entscheidet also, dass das(
falsch gewesen sein muss und löst einen SyntaxError ausEs gab auf Babel ein Fehler über sie hier auch.
quelle
() => ({console.log('Ok')}())
sie nicht mehr. Es interpretiert es also nicht wirklich so.console.log(...)
ist kein gültiger Schlüsselname.SyntaxError: Unexpected token (
(zeigt auf das(
in()
am Ende, nicht auf das(
inconsole.log(...)
).(
der Dolmetscher hat nach anstrengenden Versuchen, eine gültige Interpretation zu finden, aufgegeben und geht "das muss dann falsch sein"), was sowieso falsch sein kann, weil ich nicht weiß, wie der Dolmetscher wirklich geschrieben istDer Grund für diese Probleme ist, dass die Konsole selbst versucht, den globalen Bereich des Kontexts zu emulieren, auf den Sie gerade abzielen. Es wird auch versucht, Rückgabewerte von Anweisungen und Ausdrücken zu erfassen, die Sie in die Konsole schreiben, sodass diese als Ergebnisse angezeigt werden. Nimm zum Beispiel:
Hier wird es so ausgeführt, als wäre es ein Ausdruck, aber Sie haben es so geschrieben, als wäre es eine Aussage. In normalen Skripten würde der Wert verworfen, aber hier muss der Code intern entstellt werden (wie das Umschließen der gesamten Anweisung mit einem Funktionskontext und einer
return
Anweisung), was alle möglichen seltsamen Effekte verursacht, einschließlich der Probleme, die auftreten.Dies ist auch einer der Gründe, warum ein Teil des bloßen ES6-Codes in Skripten einwandfrei funktioniert, in der Chrome Dev Tools-Konsole jedoch nicht.
Versuchen Sie dies in der Node- und Chrome-Konsole auszuführen:
In Node oder einem
<script>
Tag funktioniert es einwandfrei, aber in der Konsole gibt esUncaught SyntaxError: Unexpected identifier
. Außerdem erhalten Sie einen Link zur Quelle, in dessen FormVMxxx:1
Sie klicken können, um die ausgewertete Quelle zu überprüfen. Diese wird angezeigt als:Warum hat es das getan?
Die Antwort ist, dass Ihr Code in einen Ausdruck konvertiert werden muss, damit das Ergebnis an den Aufrufer zurückgegeben und in der Konsole angezeigt werden kann. Sie können dies tun, indem Sie die Anweisung in Klammern setzen, wodurch sie zu einem Ausdruck wird, der obige Block jedoch auch syntaktisch falsch ist (ein Ausdruck kann keine Blockdeklaration haben).
Die Konsole versucht, diese Randfälle zu beheben, indem sie mit dem Code klug umgeht, aber das geht meiner Meinung nach über den Rahmen dieser Antwort hinaus. Sie können einen Fehler melden, um festzustellen, ob dies behoben werden kann.
Hier ist ein gutes Beispiel für etwas sehr Ähnliches:
https://stackoverflow.com/a/28431346/46588
Der sicherste Weg, um Ihren Code zum Laufen zu bringen, besteht darin, sicherzustellen, dass er als Ausdruck ausgeführt werden kann, und den Quelllink zu überprüfen, um
SyntaxError
festzustellen, wie der tatsächliche Ausführungscode lautet, und daraus eine Lösung zurückzuentwickeln. Normalerweise bedeutet dies ein Paar strategisch platzierter Klammern.Kurz gesagt: Die Konsole versucht, den globalen Ausführungskontext so genau wie möglich zu emulieren. Aufgrund der Einschränkungen der Interaktion mit der v8-Engine und der JavaScript-Semantik ist dies manchmal schwierig oder unmöglich zu lösen.
quelle
Ich habe eine Frage wie diese gestellt:
und das ist die Antwort von Kyle Simpson:
vs.
- getify (@getify) 12. Juni 2020
quelle
console.log(x)(4)
.