Warum ist "dies" in einer anonymen Funktion bei Verwendung von strict undefiniert?


84

Warum ist dies in einer anonymen Funktion undefiniert, wenn Javascript im strengen Modus verwendet wird? Ich verstehe, warum dies sinnvoll sein könnte, aber ich konnte keine konkrete Antwort finden.

Beispiel:

(function () {
    "use strict";

    this.foo = "bar"; // *this* is undefined, why?
}());

Test in einer Geige: http://jsfiddle.net/Pyr5g/1/ Überprüfen Sie den Logger (Firebug).


4
Beachten Sie, dass dies nichts mit anonymen Funktionen zu tun hat, sondern mit der Aufrufmethode. Siehe diese modifizierte Geige (siehe Konsolenprotokoll).
Phrogz

@Phrogz: Dies könnte der Grund für die Verwirrung sein. Vielen Dank für den Hinweis.
TJ.

Antworten:


101

Dies liegt daran, dass es bis ECMAscript 262 Edition 5 eine große Verwirrung gab, wenn Leute, die das constructor patternverwendeten, das newSchlüsselwort vergessen haben . Wenn Sie newbeim Aufrufen einer Konstruktorfunktion in ES3 vergessen haben, diese zu verwenden , thisauf das globale Objekt ( windowin einem Browser) verwiesen haben und das globale Objekt mit Variablen überhäufen würden.

Das war schrecklich Verhalten und damit die Menschen in ECMA beschlossen, nur um Satz thiszu undefined.

Beispiel:

function myConstructor() {
    this.a = 'foo';
    this.b = 'bar';
}

myInstance     = new myConstructor(); // all cool, all fine. a and b were created in a new local object
myBadInstance  = myConstructor(); // oh my gosh, we just created a, and b on the window object

Die letzte Zeile würde einen Fehler in ES5 strict auslösen

"TypeError: this is undefined"

(was ein viel besseres Verhalten ist)


4
Das macht Sinn. Haben Sie einen Verweis, um die Aussage zu sichern?
Rob W

1
@RobW: Ich müsste mich selbst durchsuchen, aber ich habe Douglas Crockford mehrmals gehört, wo er sagte, dies sei der Grund für diese Entscheidung.
Andy

1
Es wird in JavaScript erwähnt: The Good Parts von Crockford. Es wird ausführlich beschrieben. Nicht über die Entscheidung der ECMA.
Madr

1
Dies ist der logische Grund, warum der strikte Modus standardmäßig undefiniert ist. Der andere logische Grund ist die Effizienz, der andere logische Grund ist, dass er this === windowverwirrend ist und den globalen Geltungsbereich als Token für Funktionen
verliert

2
@jAndy: Danke für die Antwort. Das macht Sinn. Ich fand auch eine kompakte Erklärung der Änderungen dieser auf javascriptweblog.wordpress.com/2011/05/03/... : „Vor allem, wenn das erste Argument null oder nicht definiert, der dieser Wert der aufgerufenen Funktion aufzurufen oder anwenden wird nicht in das globale Objekt konvertiert. "
TJ.

15

Es gibt einen Mechanismus namens "Boxing", der das thisObjekt umschließt oder ändert, bevor er in den Kontext der aufgerufenen Funktion wechselt. In Ihrem Fall sollte der Wert von thissein, undefinedweil Sie die Funktion nicht als Methode eines Objekts aufrufen. Im nicht strengen Modus wird dies in diesem Fall durch das windowObjekt ersetzt. Im strictModus ist es immer unverändert, deshalb ist es undefinedhier.

Weitere Informationen finden Sie unter
https://developer.mozilla.org/en/JavaScript/Strict_mode


@samuel Wie können wir dem Objekt im strikten Modus eine Variable zuweisen?
Null Zeiger

8

Gemäß dieser Antwort auf diesen Stapelüberlauf können Sie thisanonyme Funktionen verwenden, indem Sie einfach .call(this)am Ende aufrufen .

(function () {
    "use strict";

    this.foo = "bar";
}).call(this);

4
Beachten Sie, dass thisdies Windowin diesem Fall das Objekt sein wird, was möglicherweise nicht erwünscht ist
Ninjakannon,

Diese Antwort erklärt die gestellte Frage nicht.
Anvesh Checka
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.