Es necesario aclarar la referencia a ECMA 5.
Supongo que significa ECMA-262 Edición 5. Cabe señalar que ECMA-262 (también conocido como ECMAScript o, menos exactamente, Javascript) es un lenguaje de programación general que se ha implementado en los navegadores de Internet. Del estándar Edition 5.1:
Los siguientes pasos se llevan a cabo cuando el control ingresa al contexto de ejecución para el código de función contenido en el objeto de función F, un llamador proporcionó thisArg y un llamador proporcionó argumentosList:
- Si el código de función es un código estricto, establezca ThisBinding en thisArg.
- De lo contrario, si thisArg es nulo o no está definido, establezca ThisBinding en el objeto global.
- De lo contrario, si Type (thisArg) no es Object, establezca ThisBinding en ToObject (thisArg).
- De lo contrario, establezca ThisBinding en thisArg
- ... (no sobre "esto")
El término "objeto global" se refiere a cualquier objeto que se encuentre en la parte superior de la cadena de alcance. Para los navegadores, este sería el objeto "ventana", pero esta es una opción de implementación (Windows Script Host tiene un objeto global invisible pero no un modo estricto, por lo que las referencias no calificadas acceden a sus propiedades y no hay un "yo" global). Además, el "modo estricto" debe habilitarse explícitamente; de lo contrario, no estará activo (sección 14.1 del estándar). Como tal, un "esto" no definido todavía se resolvería en el objeto global (ventana) en "ECMA 5" con el modo estricto no activo.
Entonces la respuesta a la pregunta es:
"esto" siempre se refiere al objeto que invoca la función. Si la función no fue invocada por un objeto (es decir, no una llamada a un método), entonces "esto" (como se le pasó a la función) es "indefinido". Sin embargo, si NO usa el modo estricto, entonces un "esto" no definido se establece en el objeto global (regla 2 anterior).
"self" no tiene un significado sintáctico especial, es solo un identificador. Los navegadores tienden a definir window.self (solo una propiedad del objeto de ventana global) = window. Esto da como resultado referencias incondicionales de que "self" es lo mismo que "window" A MENOS QUE "self" se haya redefinido dentro de un ámbito adjunto (como por ejemplo, "var self = this;" arriba. Buena suerte redefiniendo "this").
Entonces, la explicación completa del ejemplo anterior es:
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"
Una variación interesante del ejemplo crea un cierre al devolver una referencia a la función 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();
Productor
outer func: this.foo = bar
outer func: self.foo = bar
----
inner func: this.foo = blat
inner func: self.foo = bar
Tenga en cuenta que la función interna no se llama hasta que la invoca yourObject. Entonces this.foo ahora es yourObject.foo pero self todavía se resuelve en la variable en el ámbito adjunto que, en el momento en que se devolvió el objeto de función interna, era (y en el cierre resultante todavía es) myObject. Entonces, dentro de la función interna, "esto" se refiere al objeto que llama a la función interna mientras que "self" se refiere al objeto que llamó a la función externa para crear la referencia a la función interna.
Para resumir el resumen del resumen, "esto" está definido por el estándar del lenguaje, "self" lo define quien lo define (implementador de tiempo de ejecución o programador final).