5 Stimmen

EcmaScript 5 Google TechTalk - Scoping Unfall 1 Beispiel

Ich schaue mir diesen Vortrag an: http://www.youtube.com/watch?v=Kq4FpMe6cRs

// the speaker states that "'bar' is just some function 
// that invokes whatever function is passed to it"
function bar(fn) {
    fn();
}

function foo() {
    var x = 8;
    bar(function baz() { return x; });
}

Object.prototype.x = 'foo';

In Minute 35 wird das oben beschriebene Thema behandelt. Der Dozent erklärt, dass einige Browser Folgendes zurückgeben foo 代わりに 8 .

Warum?

Übrigens, während ich diese Frage schrieb, habe ich es herausgefunden, aber ich werde diese Frage trotzdem stellen, weil es ein interessantes Thema ist. :)


Live-Demo: http://jsfiddle.net/simevidas/mHyKc/

Opera 11-Warnungen 'foo' alle anderen Browser (einschließlich IE9) geben 8 .


更新しています: Ich nehme zurück, was ich gesagt habe, dass ich das herausgefunden habe. Es hat etwas damit zu tun, dass die verschachtelte Funktion eine benannte Funktion ist. Wenn Sie den Namen entfernen ( baz ), dann gibt Opera 8 was bedeutet, dass das Problem nur bei benannten verschachtelten Funktionen auftritt.

Aber warum?

4voto

ide Punkte 18477

Ich gebe zu, dass ich es nachgeschlagen habe. Ich glaube nicht, dass ich das so einfach herausgefunden hätte, um es mal so zu sagen. http://kangax.github.com/nfe/#spidermonkey-peculiarity

Um das Problem zu verstehen, ist die Semantik der benannten Funktionsausdrücke notwendig. Um den Link zu zitieren: "Der Bezeichner eines benannten Funktionsausdrucks ist nur für den lokalen Bereich einer Funktion verfügbar." Konkret bedeutet dies:

var fn = function aNamedFunction() {
  typeof aNamedFunction;  // "function"
};
typeof aNamedFunction;  // "undefined"

Um dieses Verhalten zu implementieren, erstellen SpiderMonkey und andere JS-Engines eine Dummy Umweltrahmen zwischen dem übergeordneten Rahmen (d. h. dem Bereich, in dem die Funktion definiert ist) und dem inneren Rahmen der Funktion, der bei jedem Funktionsaufruf erstellt wird. Dieser Dummy-Frame wird so konstruiert, als ob new Object() aufgerufen wurden, und enthält eine Abbildung von aNamedFunction auf das Funktionsobjekt selbst.

In dem Codebeispiel der Frage, x wird aufgelöst, indem zuerst im innersten Rahmen des Funktionsaufrufs gesucht wird. Da der Funktionskörper nicht deklariert var x; wird er nicht gefunden und der Interpreter prüft den Rahmen eine Ebene höher, den Dummy-Rahmen. Da der Dummy-Frame von new Object() (oder etwas semantisch Äquivalentes), nachschlagen x im Dummy-Frame durchläuft die Prototypenkette wie bei jedem anderen JavaScript-Objekt auch. Es sucht also Object.prototype findet die Zeichenkette 'foo' verpflichtet zu x und gibt ihn zurück.

Gott sei Dank gibt es in ES5 ein konsistentes lexikalisches Scoping.

Alternative Lektüre: http://dmitrysoshnikov.com/ecmascript/chapter-5-functions/#nfe-and-spidermonkey

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X