Perché "questo" in una funzione anonima non è definito quando si utilizza rigoroso?


86

Perché questo in una funzione anonima non è definito quando si utilizza javascript in modalità rigorosa? Capisco perché questo potrebbe avere un senso, ma non sono riuscito a trovare una risposta concreta.

Esempio:

(function () {
    "use strict";

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

Prova in un violino: http://jsfiddle.net/Pyr5g/1/ Controlla il logger (firebug).


4
Nota che questo non ha nulla a che fare con le funzioni anonime, ma con il metodo di invocazione. Guarda questo violino modificato (guarda nel registro della console).
Phrogz

@Phrogz: potrebbe essere da qui che proviene parte della confusione. Grazie per la segnalazione.
T. Junghans

Risposte:


102

È perché, fino a ECMAscript 262 edizione 5, c'era una grande confusione se le persone che utilizzavano il constructor pattern, dimenticavano di usare la newparola chiave. Se ti sei dimenticato di utilizzare newquando si chiama una funzione di costruzione in ES3, si fa thisriferimento all'oggetto globale ( windowin un browser) e si bloccherà l'oggetto globale con variabili.

E 'stato terribile comportamento e così la gente a ECMA ha deciso, solo per set thisa undefined.

Esempio:

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

L'ultima riga genererebbe un errore in ES5 strict

"TypeError: this is undefined"

(che è un comportamento molto migliore)


4
Questo ha senso. Hai un riferimento per sostenere la dichiarazione?
Rob W

1
@ RobW: avrei dovuto cercare me stesso, ma ho sentito Douglas Crockford diverse volte in cui ha detto che questo era il motivo di quella decisione.
jAndy

1
È menzionato in JavaScript: The Good Parts di Crockford. È descritto in dettaglio. Non sulla decisione dell'ECMA, però.
madr

1
Questo è il motivo logico per cui la modalità rigorosa lo imposta per impostazione predefinita su non definito. L'altro motivo logico è l'efficienza, l'altro motivo logico è che this === windowè
Raynos

2
@jAndy: grazie per la risposta. Questo ha senso. Ho anche trovato una spiegazione compatta delle modifiche a questo su javascriptweblog.wordpress.com/2011/05/03/… : "In particolare, se il primo argomento da chiamare o applicare è nullo o non definito, il valore this della funzione invocata non verrà convertito nell'oggetto globale. "
T. Junghans

15

Esiste un meccanismo chiamato "boxing" che avvolge o modifica l' thisoggetto prima di entrare nel contesto della funzione chiamata. Nel tuo caso, il valore di thisdovrebbe essere undefinedperché non stai chiamando la funzione come metodo di un oggetto. Se modalità non rigorosa, in questo caso, viene sostituita windowdall'oggetto. In strictmodalità è sempre invariato, ecco perché è undefinedqui.

Puoi trovare ulteriori informazioni su
https://developer.mozilla.org/en/JavaScript/Strict_mode


@samuel quindi come possiamo assegnare una variabile all'oggetto finestra in modalità rigorosa ??
Puntatore Nullo

8

Secondo la risposta di This Stack Overflow , puoi utilizzare thisall'interno di funzioni anonime, semplicemente chiamando .call(this)alla fine.

(function () {
    "use strict";

    this.foo = "bar";
}).call(this);

4
Si noti che thissarà l' Windowoggetto in questo caso, che potrebbe non essere desiderato
Ninjakannon

Questa risposta non spiega la domanda posta.
Anvesh Checka
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.