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).


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)


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, 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);

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.