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.