5

Stavo guardando il codice per il underscore.js library (jQuery fa la stessa cosa) e volevo solo qualche chiarimento sul motivo per cui l'oggetto della finestra viene passato nella funzione autoeseguibile.Perché è necessario passare argomenti a una funzione autoesecutiva in javascript se la variabile è globale?

Ad esempio:

(function() {   //Line 6 
    var root = this;  //Line 12 
    //Bunch of code 
}).call(this);   //Very Bottom 

Dal this è globale, perché è di essere passato alla funzione? Anche il seguente lavoro non funzionerebbe? Quali problemi potrebbero arrischiare in questo modo?

(function() { 
    var root = this; 
    //Bunch of code 
}).call(); 
+0

a quanto pare è lo stesso, è possibile inserire il codice di sottolineatura js dove è fatto? – jxs

+0

Non viene passato alcun argomento - 'call' viene usato per impostare' this' all'interno del callback. Tuttavia, non vedo perché questo sia necessario unicamente dal codice che hai pubblicato. – apsillers

+0

La funzione inizia alla riga 6, la radice variabile viene declassata sulla riga 12 e quindi la chiamata si trova nella parte inferiore. L'intero file è una grande funzione. – KingKongFrog

risposta

4

Sospetto che il motivo sia ECMAScript 5 strict mode.

In modalità non rigorosa, questo IIFE

(function() { 
    console.log(this); // window or global 
})(); 

registra l'oggetto window (o l'oggetto global, se siete su un server node.js), perché l'oggetto globale è fornito come this a funzioni che non vengono eseguite come metodo di un oggetto.

Confronta quel risultato a

"use strict"; 
(function() { 
    console.log(this); // undefined 
})(); 

In modalità rigorosa, il this di una funzione bare-invocata non è definito. Pertanto, gli autori di Underscore utilizzano call per fornire un esplicito this alla funzione anonima in modo che sia standardizzato in modalità rigorosa e non rigida. Il semplice richiamo della funzione (come ho fatto nei miei esempi) o l'utilizzo di .call() porta a un'incoerenza che può essere risolta con .call(this).

1

jQuery fa la stessa cosa, e si possono trovare diverse risposte alla tua domanda sul SO effettuando una ricerca in tal senso.

Ci sono due ragioni per avere una variabile globale sempre disponibile come window in ambito locale, che sono entrambi a fini di ottimizzazioni relativamente minori: tempo

  1. caricamento. La ricerca di una variabile locale richiede un po 'meno di tempo rispetto alla ricerca di una variabile globale, perché l'interprete non deve guardare fino alla struttura del contesto. Per tutta la durata di una funzione, la dimensione di Underscore o jQuery, che può teoricamente sommarsi a una quantità di tempo inferiore a quella delle macchine più lente.

  2. Dimensioni file. La minifrazione di Javascript si basa sul fatto che le variabili possono essere nominate qualsiasi cosa fintanto che sono coerenti. myLongVariableName diventa a nella versione minificata. Il problema, ovviamente, è che questo può essere applicato solo alle variabili definite all'interno della sceneggiatura; tutto ciò che sta tirando dall'esterno deve mantenere lo stesso nome, perché se riduci lo window al numero pr l'interprete non saprà di cosa diavolo stai parlando. Con shadowing con un riferimento a se stessa, Minify può fare cose come:

    (function(A){ B(A, {...}); A.doStuff(); //etc });})(window) 
    

    e ogni volta che si sarebbe altrimenti messo window (6 caratteri) ora avete A (1 carattere). Anche in questo caso, non è importante, ma in un file di grandi dimensioni che deve chiamare esplicitamente lo window per la gestione dell'ambito può essere importante e hai già ottenuto un vantaggio di alcuni caratteri se lo usi due volte. E nelle grandi librerie popolari che vengono servite da server limitati e da persone che potrebbero disporre di pessimi piani Internet, ogni byte conta.


Modifica dopo aver letto i commenti su domanda:

Se guardate what function.call() actually does, il secondo frammento non sarebbe effettivamente lavorare - il this essere passato in non è un argomento, è un esplicito chiamando contesto per la funzione, e devi fornire a .call(). La riga all'inizio del file serve ai due scopi precedenti. La ragione per impostare esplicitamente il contesto con call è la protezione futura: al momento, le funzioni anonime ottengono il contesto globale, ma in teoria potrebbero cambiare, essere scoraggiate in una specifica ECMA futura o comportarsi in modo strano su un browser di nicchia. Per qualcosa che usa la metà di Internet, è meglio essere più espliciti ed evitare completamente il problema. La scelta di this/window al livello più alto, penso che debba avere qualcosa a che fare con la preoccupazione per i dispositivi non PC (cioè mobili) potenzialmente usando un nome diverso per il loro oggetto di livello superiore.