Por que “this” em uma função anônima é indefinido ao usar estrito?

85

Por que isso está em uma função anônima indefinida ao usar javascript no modo estrito? Eu entendo por que isso pode fazer sentido, mas não consegui encontrar uma resposta concreta.

Exemplo:

(function () {
    "use strict";

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

Teste em um violino: http://jsfiddle.net/Pyr5g/1/ Verifique o logger (firebug).

T. Junghans
fonte
4
Observe que isso não tem nada a ver com funções anônimas, mas com o método de invocação. Veja este violino modificado (veja o log do console).
Phrogz
@Phrogz: Pode ser daí que veio parte da confusão. Obrigado por apontar isso.
T. Junghans,

Respostas:

101

É porque, até ECMAscript 262 edição 5, havia uma grande confusão se as pessoas que estavam usando o constructor pattern, esqueciam de usar a newpalavra - chave. Se você esqueceu de usar newao chamar uma função de construtor no ES3, thisreferenciou o objeto global ( windowem um navegador) e você iria sobrecarregar o objeto global com variáveis.

Que era um comportamento terrível e para que as pessoas em ECMA decidiu, apenas para definir thisa undefined.

Exemplo:

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

A última linha lançaria um erro no ES5 estrito

"TypeError: this is undefined"

(que é um comportamento muito melhor)

Andy
fonte
4
Isso faz sentido. Você tem uma referência para fazer backup da declaração?
Rob W
1
@RobW: Eu mesmo teria que fazer uma busca, mas ouvi Douglas Crockford várias vezes em que ele disse que esse era o motivo dessa decisão.
jAndy
1
É mencionado em JavaScript: The Good Parts de Crockford. Ele é descrito em detalhes. Não sobre a decisão da ECMA, no entanto.
madr.
1
Esta é a razão lógica pela qual o modo estrito padroniza para indefinido. A outra razão lógica é a eficiência, a outra razão lógica é que this === windowé confuso e vaza o escopo global como um token em funções
Raynos
2
@jAndy: Obrigado pela resposta. Isso faz sentido. Eu também encontrei uma explicação compacta das alterações para este sobre javascriptweblog.wordpress.com/2011/05/03/... : "Mais notavelmente, se o primeiro argumento para chamar ou aplicar é nulo ou indefinido, a este valor da função chamada não será convertido para o objeto global. "
T. Junghans
15

Existe um mecanismo chamado "boxing" que envolve ou altera o thisobjeto antes de entrar no contexto da função chamada. No seu caso, o valor de thisdeveria ser undefinedporque você não está chamando a função como um método de um objeto. Se o modo não for estrito, neste caso, ele será substituído pelo windowobjeto. No strictmodo está sempre inalterado, é por isso que está undefinedaqui.

Você pode encontrar mais informações em
https://developer.mozilla.org/en/JavaScript/Strict_mode

Samuel Rossille
fonte
@samuel então como podemos atribuir uma variável ao objeto janela no modo estrito ??
Null Pointer
8

De acordo com a resposta de This Stack Overflow , você pode usar thisfunções anônimas internas, simplesmente chamando .call(this)no final dela.

(function () {
    "use strict";

    this.foo = "bar";
}).call(this);
ReverseTales
fonte
4
Observe que thisserá o Windowobjeto neste caso, o que pode não ser desejado
Ninjakannon
Esta resposta não explica a pergunta feita.
Anvesh Checka