2013-02-28 10 views
6

Testato qualche codice js in Chrome Dev Console e sono un po 'confuso.JavaScript 'use strict'; all'interno delle funzioni

So che in rigorosa modalità funzioni che non sono i metodi di un oggetto quando denominato questo parola chiave dovrebbe ricevere indefinita invece di oggetto globale.

function test(){ 
    "use strict"; 
    return this===undefined;} 
test(); 

uscite falsa.

"use strict"; 
function test(){ 
    return this===undefined;} 
test(); 

Ancora falsa.

(function test(){ 
    "use strict"; 
    return this===undefined;}()); 

uscite vero.

Volevo solo chiarire. ʕ • ᴥ • ʔ Sono nuovo di js.

+2

Si prega di leggere una domanda simile http://stackoverflow.com/questions/1335851/what-does-use-strict-do-in-javascript-and-what-is-the-reasoning-behind-it – hexblot

+4

@hexblot questo però non risponde alla domanda ... – Christoph

risposta

2

E ' è un bug nella console per gli sviluppatori di Chromium che fa sì che this si riferisca ancora all'oggetto globale. Lo stesso codice funziona come specificato con javascript: nella barra degli indirizzi e nei documenti.

È possibile verificare che in questo modo (ingressi 2 console):

var global = (function() { return this; }()); 

"use strict"; 
function test() { return this === global; } 
test(); 

e (uno o più ingressi console)

var script = document.createElement("script"); 
script.type = "text/javascript"; 
script.appendChild(document.createTextNode(
    'function test() { "use strict"; return this === undefined; }; console.log(test());' 
)); 
document.body.appendChild(script); 

testato in cromo versione 25.0.1364.97 Debian 7.0 (183676) .

+0

Il tuo primo test è un test non funzionante. Anche se lo si esegue in un tag script anziché in console, si otterrà comunque 'true', perché' "use strict" 'deve essere la * prima * riga nel suo scope. Il tuo esempio ha in arrivo 'var global ...', quindi la direttiva viene ignorata (come da specifica). –

+0

@NathanWall No, vedi il mio chiarimento. Ti suggerisco di usare 'debugger;' nella funzione per ispezionare lo stack delle chiamate. – PointedEars

2

Tutto bene. Se si esegue il codice tramite una pagina HTML (non una console di sviluppo), i risultati soddisfano le aspettative (sempre this===undefined).

Inoltre, nel più recente di Firefox (Firebug):

function test(){ 
    "use strict"; 
    return this===undefined;} 
test(); 
>> true 

Quindi questo sembra essere solo bug di un altro Chrome (funzione?). Sembra che abbia un approccio leggermente diverso al codice che viene passato tramite la console di sviluppo.

Si noti inoltre che le questioni di ordine:

<script> 
    console.log('Me First!'); 

    "use strict"; 

    function test(){ 
     console.log(this); 
    } 
    test(); 

</script> 

>>> "Me First!" 
>>> Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…} 

Ma:

<script> 
    "use strict"; 

    console.log('Me later!'); 

    function test(){ 
     console.log(this); 
    } 
    test(); 

</script> 

>>> undefined 
>>> "Me later!" 
4

Quello che ho notato è semplicemente un effetto collaterale del modo in cui gli sviluppatori opere della console. Quando si entra codice di là, questo è effettivamente ciò che accade (vedi this answer per maggiori dettagli):

eval.call(null, "with (window) { \ 
        function test() { \ 
         'use strict'; \ 
         console.log(this); \ 
        } test(); \ 
       }"); 

Questa è una indiretta chiamata a eval, il che significa che sarà sempre eseguito nel contesto di esecuzione globale (nel browser, ovvero window).

In effetti, la funzione viene legato all'oggetto globale e quindi this contiene un riferimento all'oggetto globale, come se avete fatto queste cose in una pagina web (piuttosto che nella console):

function test(){ 
    "use strict"; 
    return this === undefined; 
} 

test(); // true 
test.call(window); // false 
+1

Un oggetto come quello indicato da 'window' * è * * non * un contesto di esecuzione. Un contesto di esecuzione è un'entità di programma astratto; ha una * catena di scope * con oggetti in essa contenuti. In questo caso, sarebbe l'istruzione 'with' che inserisce l'oggetto indicato da' window' nella catena di scope per il contesto della chiamata 'test()'. – PointedEars

+0

@PointedEars - Sì, certo. Avrei potuto dire "il record dell'ambiente dell'ambiente lessicale a cui appartiene l'oggetto' window' ", ma il modo in cui l'ho inserito è stato più semplice e penso che abbia ancora il merito. E l'istruzione 'with' non fa alcuna differenza in questo caso - è il modo in cui 'eval' viene chiamato che influenza il contesto in cui viene valutato il suo argomento. –

+0

L'istruzione 'with' qui * potrebbe * essere sostanziale; è certamente se si assume (IMO erroneamente) che la proprietà host 'window' dell'oggetto globale si riferisce sempre all'oggetto globale. Perché quindi la chiamata 'test()' sarebbe equivalente a 'global.window.test()', dove 'global' sarebbe un sostituto per il riferimento standard all'oggetto globale. – PointedEars