A referência ao ECMA 5 precisa ser esclarecida.
Presumo que signifique ECMA-262 Edição 5. Deve-se observar que ECMA-262 (também conhecido como ECMAScript ou, menos precisamente, Javascript) é uma linguagem de script geral que foi implementada em navegadores da Internet. Do padrão da edição 5.1:
As etapas a seguir são realizadas quando o controle entra no contexto de execução para o código de função contido no objeto de função F, um chamador fornecido thisArg e um chamador fornecido argumentsList:
- Se o código da função for um código estrito, defina ThisBinding como thisArg.
- Caso contrário, se thisArg for nulo ou indefinido, defina ThisBinding como o objeto global.
- Caso contrário, se Type (thisArg) não for Object, defina ThisBinding como ToObject (thisArg).
- Caso contrário, defina ThisBinding como thisArg
- ... (não sobre "isso")
O termo "objeto global" se refere a qualquer objeto que esteja no topo da cadeia de escopo. Para navegadores, este seria o objeto "janela", mas é uma opção de implementação (o Windows Script Host tem um objeto global invisível, mas nenhum modo estrito, portanto, referências não qualificadas acessam suas propriedades e não há um "self" global). Além disso, o "modo estrito" deve ser ativado explicitamente, caso contrário, não estará ativo (seção 14.1 da norma). Como tal, um indefinido "this" ainda resolveria para o objeto global (janela) em "ECMA 5" com o modo estrito não ativo.
Portanto, a resposta à pergunta é:
"this" sempre se refere ao objeto que invoca a função. Se a função não foi chamada por um objeto (ou seja, não por uma chamada de método), então "this" (conforme passado para a função) é "indefinido". No entanto, se NÃO estiver usando o modo estrito, um "this" indefinido será definido para o objeto global (regra 2 acima).
"self" não tem nenhum significado sintático especial, é apenas um identificador. Os navegadores tendem a definir window.self (apenas uma propriedade do objeto global window) = window. Isso resulta em referências não qualificadas a "self" sendo o mesmo que "window" A MENOS que "self" tenha sido redefinido dentro de um escopo abrangente (como por "var self = this;" acima. Boa sorte ao redefinir "this".)
Portanto, a explicação completa do exemplo acima é:
outer func: this.foo = bar
// "this" refers to the invoking object "myObject"
outer func: self.foo = bar
// "self" resolves to the variable in the local scope which has been set to "this" so it is also "myObject"
inner func: this.foo = undefined
// "this" refers to the invoking object (none) and so is replaced by the global object (strict mode must be off). "window" has no foo property so its "value" is undefined.
inner func: self.foo = bar
// self resolves to the variable in the enclosing scope which is still "myObject"
Uma variação interessante do exemplo cria um fechamento, retornando uma referência à função interna.
var myObject = {
foo: "bar",
func: function() {
var self = this;
console.log("outer func: this.foo = " + this.foo);
console.log("outer func: self.foo = " + self.foo);
return function() {
console.log("inner func: this.foo = " + this.foo);
console.log("inner func: self.foo = " + self.foo);
};
}
};
var yourObject = {
foo: "blat",
func: myObject.func() // function call not function object
};
console.log("----");
yourObject.func();
Produzindo
outer func: this.foo = bar
outer func: self.foo = bar
----
inner func: this.foo = blat
inner func: self.foo = bar
Observe como a função interna não é chamada até que seja invocada por seuObjeto. Portanto, this.foo agora é seuObjeto.foo, mas self ainda é resolvido para a variável no escopo envolvente que, no momento em que o objeto de função interna foi retornado, era (e no fechamento resultante ainda é) meuObjeto. Portanto, dentro da função interna, "this" se refere ao objeto que chama a função interna, enquanto "self" se refere ao objeto que chamou a função externa para criar a referência à função interna.
Para resumir o resumo do resumo, "this" é definido pelo padrão de linguagem, "self" é definido por quem o define (implementador de tempo de execução ou programador final).