¿Por qué "esto" en una función anónima no está definido cuando se usa estricto?

85

¿Por qué no está definido esto en una función anónima cuando se usa javascript en modo estricto? Entiendo por qué esto podría tener sentido, pero no pude encontrar una respuesta concreta.

Ejemplo:

(function () {
    "use strict";

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

Prueba en un violín: http://jsfiddle.net/Pyr5g/1/ Revisa el registrador (firebug).

T. Junghans
fuente
4
Tenga en cuenta que esto no tiene nada que ver con funciones anónimas, sino con el método de invocación. Vea este violín modificado (busque en el registro de la consola).
Phrogz
@Phrogz: De aquí puede ser de donde vino parte de la confusión. Gracias por señalar eso.
T. Junghans

Respuestas:

101

Es porque, hasta ECMAscript 262 edición 5, había una gran confusión si las personas que usaban el constructor pattern, olvidaban usar la newpalabra clave. Si olvidó usar newal llamar a una función de constructor en ES3, thishaga referencia al objeto global ( windowen un navegador) y golpearía el objeto global con variables.

Ese fue un comportamiento terrible y la gente de ECMA decidió thishacerlo undefined.

Ejemplo:

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

La última línea arrojaría un error en ES5 estricto

"TypeError: this is undefined"

(que es un comportamiento mucho mejor)

jAndy
fuente
4
Esto tiene sentido. ¿Tiene una referencia para respaldar la declaración?
Rob W
1
@RobW: Tendría que registrarme yo mismo, pero escuché a Douglas Crockford varias veces donde dijo, esta fue la razón de esa decisión.
jAndy
1
Se menciona en JavaScript: The Good Parts de Crockford. Se describe en detalle. Sin embargo, no se trata de la decisión de ECMA.
madr
1
Esta es la razón lógica por la que el modo estricto lo establece de forma predeterminada en indefinido. La otra razón lógica es la eficiencia, la otra razón lógica es que this === windowes confusa y filtra el alcance global como un token en funciones
Raynos
2
@jAndy: Gracias por la respuesta. Esto tiene sentido. También encontré una explicación compacta de los cambios a esto en javascriptweblog.wordpress.com/2011/05/03/… : "Más notablemente, si el primer argumento para llamar o aplicar es nulo o indefinido, este valor de la función invocada no se convertirá al objeto global. "
T.Junghans
15

Existe un mecanismo llamado "boxing" que envuelve o cambia el thisobjeto antes de ingresar al contexto de la función llamada. En su caso, el valor de thisdebería ser undefinedporque no está llamando a la función como un método de un objeto. Si el modo no es estricto, en este caso, se reemplaza por el windowobjeto. En el strictmodo siempre no cambia, por eso está undefinedaquí.

Puede encontrar más información en
https://developer.mozilla.org/en/JavaScript/Strict_mode

Samuel Rossille
fuente
@samuel, entonces, ¿cómo podemos asignar una variable a un objeto de ventana en modo estricto?
Puntero nulo
8

De acuerdo con la respuesta de This Stack Overflow , puede usar thisfunciones anónimas internas, simplemente llamando .call(this)al final.

(function () {
    "use strict";

    this.foo = "bar";
}).call(this);
ReverseTales
fuente
4
Tenga en cuenta que thisserá el Windowobjeto en este caso, que puede no ser deseado
Ninjakannon
Esta respuesta no explica la pregunta formulada.
Anvesh Checka