Ich fange an, JavaScript-Muster zu lesen , einige Codes haben mich verwirrt.
var global = (function () {
return this || (1, eval)('this');
}());
Hier sind meine Fragen:
Q1:
(1, eval) === eval
?
Warum und wie funktioniert es?
F2: Warum nicht einfach
var global = (function () {
return this || eval('this');
}());
oder
var global = (function () {
return this;
}());
javascript
eval
Shawjia
quelle
quelle
Antworten:
Der Unterschied zwischen
(1,eval)
und einfach alteval
ist, dass Ersteres ein Wert ist und letzteres ist. Es wäre offensichtlicher, wenn es eine andere Kennung wäre:Das ist
(1,eval)
ein Ausdruck, der nachgibteval
(genau wie sagen,(true && eval)
oder(0 ? 0 : eval)
würde), aber es ist kein Hinweis aufeval
.Warum kümmert es dich?
Nun, die Ecma-Spezifikation berücksichtigt einen Verweis auf
eval
einen „direkten eval Anruf“ zu sein, sondern einen Ausdruck, der lediglich ergibteval
eine indirekter zu sein - und indirekte eval Anrufe werden in globalem Bereich auszuführen garantiert.Dinge, die ich immer noch nicht weiß:
this
Funktion einer Funktion im globalen Bereich das globale Objekt nicht ergeben?Weitere Informationen finden Sie hier .
BEARBEITEN
Anscheinend lautet die Antwort auf meine erste Frage "fast immer". Ein direkter
eval
wird aus dem aktuellen Bereich ausgeführt. Betrachten Sie den folgenden Code:Es überrascht nicht (heh-heh), dies druckt aus:
BEARBEITEN
Nach weiteren Experimenten werde ich vorläufig sagen, dass
this
dies nicht aufnull
oder eingestellt werden kannundefined
. Es kann auf andere falsche Werte (0, '', NaN, false) gesetzt werden, aber nur sehr absichtlich.Ich werde sagen, dass Ihre Quelle unter einer milden und reversiblen kranio-rektalen Inversion leidet und möglicherweise eine Woche lang in Haskell programmieren möchte.
quelle
value
vslvalue
Ding ( na ja, in der Praxis vielleicht, aber nicht in Worten). Noch die ES5-Bewertungsregeln (nicht, dass ich sie vernünftigerweiseeval
jemals verwenden müsste ). Vielen Dank!eval
hat viele böse scharfe Kanten und sollte nur als letztes Mittel und dann sehr, sehr vorsichtig verwendet werden.innerHtml
eval
der MemberExpression-Teil einer CallExpression sein muss und sein muss und sich auf die Standardfunktion beziehteval
.eval
als Ziel eines Aufrufausdrucks bezeichnet wird, ist etwas Besonderes. Sie geben an, dass ECMA Verweise aufeval
spezielle Ereignisse behandelt , die dies nicht tut. Es ist die Platzierung im Aufrufausdruck, die besonders ist und die der Ausdruck als Standardfunktion auswerteteval
. Zum Beispielvar eval = window.eval; eval('1');
ist es immer noch eine direkte Bewertung und auchwindow.eval('1')
nicht, obwohl die Bewertung auch in diesem Fall ein Wert ist.Das Fragment,
wird das globale Objekt auch im strengen Modus korrekt auswerten. Im nicht strengen Modus ist der Wert von
this
das globale Objekt, im strengen Modus jedochundefined
. Der Ausdruck(1, eval)('this')
wird immer das globale Objekt sein. Der Grund dafür sind die Regeln für indirekte Verse direkteval
. Direkte Aufrufe voneval
haben den Gültigkeitsbereich des Aufrufers und die Zeichenfolgethis
würde den Wert vonthis
in der Schließung ergeben. Indirekteeval
s werden im globalen Bereich ausgewertet, als ob sie innerhalb einer Funktion im globalen Bereich ausgeführt würden. Da diese Funktion selbst keine Funktion im strengen Modus ist, wird das globale Objekt als übergebenthis
und der Ausdruck wird dann'this'
an das globale Objekt ausgewertet. Der Ausdruck soll indirekt sein und das globale Objekt zurückgeben.(1, eval)
ist nur eine ausgefallene Art, das zu erzwingeneval
A1:
(1, eval)('this')
ist nicht dasselbe wieeval('this')
wegen der Sonderregeln für indirekte Verse, die direkt aufgerufen werdeneval
.A2: Das Original arbeitet im strengen Modus, die geänderten Versionen nicht.
quelle
Zu Q1:
Ich denke, dies ist ein gutes Beispiel für einen Kommaoperator in JS. Ich mag die Erklärung für Kommaoperatoren in diesem Artikel: http://javascriptweblog.wordpress.com/2011/04/04/the-javascript-comma-operator/
Der Kommaoperator wertet beide Operanden aus (von links nach rechts) und gibt den Wert des zweiten Operanden zurück.
Zu Q2:
(1, eval)('this')
wird als indirekter Auswertungsaufruf betrachtet, der in ES5 Code global ausführt. Das Ergebnis wird also der globale Kontext sein.Siehe http://perfectionkills.com/global-eval-what-are-the-options/#evaling_in_global_scope
quelle
Q1: Mehrere aufeinanderfolgende Javascript-Anweisungen, die durch ein Komma getrennt sind, nehmen den Wert der letzten Anweisung an. So:
(1, eval)
Nimmt den Wert des letzten, der eine Funktionsreferenz auf dieeval()
Funktion ist. Dies geschieht anscheinend auf diese Weise, um deneval()
Anruf in einen indirekten Bewertungsaufruf umzuwandeln, der in ES5 im globalen Bereich ausgewertet wird. Details hier erklärt .F2: Es muss eine Umgebung geben, die kein globales definiert
this
, aber definierteval('this')
. Das ist der einzige Grund, an den ich denken kann.quelle
/eval\(/g
?eval
Code in seinem eigenen Kontext ausgeführt und nicht im globalen Kontext oder im umschließenden Kontext. Eine Möglichkeit, dies zu umgehen, besteht darin, indirekt darauf zu verweisen, wie es der betreffende Code tut.