2012-10-08 10 views
5

Supponiamo di avere il seguente script, chiamato include_strict.js. Dopo esegue dovrei avere window.global1 definito:"use strict"; + jQuery.getScript() = lo script non può esportare nello spazio dei nomi globale

"use strict"; 

var globalVar = {}; 
alert(typeof window.globalVar); 

Ma se includo da un blocco di JavaScript con

$.getScript("include_strict.js"); 

L'avviso dice undefined. Perché? Che cosa sta succedendo qui?

Cordiali saluti, non è quello che succede se includere il file utilizzando un tag script:

<script type="text/javascript" src="include_strict.js"></script> 

Ecco, vedo l'avviso previsto, object. E se rimuovo "use strict";, quindi entrambi jQuery.getScript() e <script>; hanno lo stesso effetto di visualizzare object.

Ho creato un esempio (https://docs.google.com/file/d/0B-XXu97sL1Ckb0x0OHptTmVMY00/edit) per dimostrarlo.

risposta

11

Esso utilizza $.getScript() che utilizza eval per eseguire lo script che non può modificare la portata globale in modalità rigorosa:

In secondo luogo, eval di rigoroso codice di modalità non introduce nuove variabili nel campo di applicazione circostante. Nel codice normale eval("var x;") viene introdotta una variabile x nella funzione circostante o nell'ambito globale. Ciò significa che, in generale, in una funzione che contiene una chiamata per evalare ogni nome che non si riferisce a un argomento o una variabile locale deve essere mappata su una particolare definizione in fase di esecuzione (poiché tale valutazione potrebbe aver introdotto una nuova variabile che nascondeva la variabile esterna). In modalità rigorosa eval crea variabili solo per il codice in corso di valutazione, in modo da eval non può incidere se un nome si riferisce ad una variabile esterna o qualche variabile locale:

Fonte: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/Strict_mode

La soluzione non sta usando jQuery per caricare lo script ma aggiungendo un elemento script al DOM. Nota che non puoi nemmeno usare jQuery per aggiungere l'elemento; userà automaticamente $.getScript() per questo.

+0

Mi battuto da alcuni secondi ;-) – Prinzhorn

+0

Molto interessante. Ho appena scoperto questo problema per la prima volta e ha perfettamente senso. Il mio problema è che ho bisogno di eseguire diversi script in ordine dopo che sono stati caricati, quindi ho bisogno di sapere quando lo script è stato caricato prima di aggiungere lo script successivo. C'è un modo per sapere se uno script è stato caricato se utilizzo il metodo di aggiunta dello script al DOM? would .load() funziona? – Redtopia

2

jQuery eval uates lo script. "usa rigoroso;" all'interno di eval cambia la semantica del codice. Ecco perché la modalità rigorosa può essere pericolosa! Perché nei browser che non lo supportano, il tuo codice fa qualcos'altro.

In secondo luogo, l'eval del codice della modalità rigorosa non introduce nuove variabili nello scope circostante. Nel codice normale eval ("var x;") introduce una variabile x nella funzione circostante o l'ambito globale. Ciò significa che, in generale, in una funzione che contiene una chiamata per evalare ogni nome che non si riferisce a un argomento o una variabile locale deve essere mappata su una particolare definizione in fase di esecuzione (poiché tale valutazione potrebbe aver introdotto una nuova variabile che nascondeva la variabile esterna). In modalità rigorosa eval crea variabili solo per il codice che viene valutato, quindi eval non può influenzare se un nome fa riferimento a una variabile esterna oa una variabile locale.

https://developer.mozilla.org/en/JavaScript/Strict_mode

La soluzione è quella di utilizzare window.foo = "bar;" anziché var foo = "bar";. E dovresti inserire il tuo codice all'interno di un IIFE per renderlo "use strict"; più prevedibile.

(function(window) { 
    "use strict"; 

    window.globalVar = {}; 
    alert(typeof window.globalVar); 
}(window)); 
+0

Non è esattamente quello di cui avevo bisogno, ma mi ha fatto "click" - grazie mille! :) –

0

processo la risposta di rimuovere la modalità rigoroso prima esecuzione:

$.ajax({ 
    url: scriptUrl, 
    dataType: "script", 
    dataFilter: function (data, type) { 
     return data.replace("\'use strict\';", ""); 
    } 
});