Dlaczego „this” w funkcji anonimowej jest nieokreślone, gdy używana jest funkcja ścisła?

85

Dlaczego w funkcji anonimowej jest to niezdefiniowane, gdy używasz javascript w trybie ścisłym? Rozumiem, dlaczego to może mieć sens, ale nie mogłem znaleźć żadnej konkretnej odpowiedzi.

Przykład:

(function () {
    "use strict";

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

Testuj na skrzypcach: http://jsfiddle.net/Pyr5g/1/ Sprawdź loggera (firebug).

T. Junghans
źródło
4
Zauważ, że nie ma to nic wspólnego z funkcjami anonimowymi, ale z metodą wywołania. Zobacz to zmodyfikowane skrzypce (spójrz w dzienniku konsoli).
Phrogz
@Phrogz: To może być przyczyna zamieszania. Dziękuję za zwrócenie uwagi.
T. Junghans,

Odpowiedzi:

101

To dlatego, że aż do ECMAscript 262 wydanie 5 było duże zamieszanie, gdy ludzie, którzy używali constructor pattern, zapomnieli użyć newsłowa kluczowego. Jeśli zapomniałeś użyć funkcji newpodczas wywoływania funkcji konstruktora w ES3, odwołałeś się thisdo obiektu globalnego ( windoww przeglądarce) i zrzuciłbyś obiekt globalny zmiennymi.

To było okropne zachowanie, więc ludzie z ECMA zdecydowali się po prostu na thisto undefined.

Przykład:

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

Ostatnia linia spowodowałaby błąd w ES5 strict

"TypeError: this is undefined"

(co jest znacznie lepszym zachowaniem)

jAndy
źródło
4
To ma sens. Czy masz odniesienie do kopii zapasowej oświadczenia?
Rob W
1
@RobW: Musiałbym sam przeszukać, ale kilka razy słyszałem Douglasa Crockforda, gdy mówił, że to był powód tej decyzji.
jAndy
1
Wspomina o tym JavaScript: The Good Parts autorstwa Crockforda. Jest szczegółowo opisane. Nie chodzi jednak o decyzję ECMA.
madr
1
Jest to logiczny powód, dla którego tryb ścisły domyślnie ustawia to na niezdefiniowane. Drugim logicznym powodem jest wydajność, innym logicznym powodem jest to, że this === windowjest myląca i przecieka globalny zasięg jako symbol funkcji
Raynos
2
@jAndy: Dzięki za odpowiedź. To ma sens. Znalazłem również zwięzłe wyjaśnienie zmian w tym na javascriptweblog.wordpress.com/2011/05/03/… : „Przede wszystkim, jeśli pierwszy argument do wywołania lub zastosowania jest zerowy lub nieokreślony, wartość wywoływanej funkcji nie zostaną przekonwertowane na obiekt globalny ”.
T. Junghans
15

Istnieje mechanizm zwany „boksowaniem”, który zawija lub zmienia thisobiekt przed wejściem w kontekst wywoływanej funkcji. W twoim przypadku wartość thispowinna być taka, undefinedponieważ nie wywołujesz funkcji jako metody obiektu. W tym przypadku w trybie innym niż ścisły jest to zastępowane przez windowobiekt. W stricttrybie jest zawsze niezmieniony, dlatego jest undefinedtutaj.

Więcej informacji można znaleźć pod
adresem https://developer.mozilla.org/en/JavaScript/Strict_mode

Samuel Rossille
źródło
@samuel, więc jak możemy przypisać zmienną do obiektu okna w trybie ścisłym?
Wskaźnik
8

Zgodnie z odpowiedzią This Stack Overflow , możesz używać thiswewnątrz funkcji anonimowych, po prostu wywołując .call(this)na końcu.

(function () {
    "use strict";

    this.foo = "bar";
}).call(this);
ReverseTales
źródło
4
Zauważ, że thisbędzie to Windowobiekt w tym przypadku, co może nie być pożądane
Ninjakannon
Ta odpowiedź nie wyjaśnia zadanego pytania.
Anvesh Checka