簡體   English   中英

JavaScript 變量如何工作?

[英]How do JavaScript variables work?

我知道 JavaScript 變量指向一個值:

var foo = true;
//... later 
foo = false;

所以在那個例子中,我改變了foo指向true -> foo指向false ,但如果我這樣做:

for (var i=0; i<100; i++){
    var someVar = i;
}

我是否為每次迭代創建一個新的 var?

以下兩種方式做同樣的事情有什么區別嗎?

var myvar;
for (var i=0; i<100; i++){
    myvar = i;
}

for (var i=0; i<100; i++){
    var myvar = i;
}

如果是這樣,為什么?

在 Javascript ES5 及更早版本中沒有塊作用域,只有函數作用域。 此外,在函數范圍內聲明的所有 javascript 變量的聲明都會自動“提升”到函數的頂部。

因此,在循環中聲明變量與在函數頂部聲明然后在循環中引用它沒有什么不同。

有關一些有用的解釋,請參閱這兩個參考資料: http : //www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoistinghttp://net.tutsplus.com/tutorials/javascript-ajax/quick-tip -javascript-hoisting-explained/

注意:對變量的賦值不會被提升,只是變量的聲明。 所以,如果你這樣做:

function a() {
    for (var i=0; i<100; i++){
        var myvar = i;
    }
}

它是這樣工作的:

function a() {
    var myvar;
    for (var i=0; i<100; i++){
        myvar = i;
    }
}

如果你想在你的for循環中創建一個新的作用域,你可以像這樣使用 IIFE(立即調用的函數表達式):

function a() {
    for (var i=0; i<100; i++){
        (function() {
            var myvar = i;
            // myvar is now a separate variable for each time through the for loop
        })();
    }
}

2015 年更新。 ES6(或有時稱為 ES2015)提供了let聲明,它確實提供了塊作用域。 在這種情況下,一個let變量聲明只會被提升到當前塊作用域的頂部。 截至 2015 年年中,這尚未在瀏覽器中廣泛實現,但即將推出,它可以在 node.js 等服務器端環境中或通過轉譯器使用。

所以,在 ES6 中,如果你這樣做:

for (let i=0; i<100; i++){
    let someVar = i;
}

isomeVar都只是循環本地的。

不,沒有區別; 在 JavaScript 中,變量的作用域是函數級別,而不是塊級別。

正如@icktoofay 所說,在 javascript 中沒有區別。 在某些語言中,在每次迭代中,變量將被實例化,然后超出范圍,並留給垃圾收集。

要在 javascript 中模擬這一點,您可以執行以下操作:

for (var i=0; i<100; i++){
    (function(){
        var myvar = i;
    })();
}

在這種情況下,myvar 只存在於匿名函數的范圍內,因此在每次迭代時,都會創建一個新的 myvar 實例。

JSLint 之類的工具建議您將所有var語句放在函數的頂部。 這是因為如果您不這樣做,JavaScript 基本上會為您完成,因此如果您這樣做,就不會那么混亂。 在您的示例中,只要它出現在myvar一個定義之前,將var放在哪里並不重要。 同樣,您也可以在函數頂部聲明i

更有趣的是分層作用域鏈,當 JavaScript 想要查找名稱時,它會在其中搜索名稱。 它從本地全局搜索作用域鏈,直到找到所述名稱的第一個實例。

這就是為什么你可以玩這樣的游戲來惹惱你的朋友:

function foofinder() {
    var bar = function () { return foo; },
        foo="beers";
    return bar();
}

foofinder();
>>> "beers"

通過在變量名之前不斷聲明var ,您可以指示 JavaScript 引擎或解釋器在賦值之前將變量重新初始化為未定義的值( undefined ,而不是數字、字符串/文本、布爾值或null ),即將是額外的指令,減慢循環執行的速度。 您還增加了代碼大小並降低了解析/解釋/編譯代碼的速度。

對於幾乎任何應用程序,都沒有功能差異,但仍然存在差異,並且在數十萬或數十億次循環執行后差異可能會很明顯。 但是,在函數中重復使用同名 VAR 聲明會導致 Chrome / V8 中的致命異常。

更新:事實證明,在變量名之前使用var比省略 var,如下面在 Chrome / v8 上使用 JavaScript 控制台運行的基准測試所證明的那樣。

var startTime = new Date().getTime();
var myvar;
for (var i=0; i<100000; i++){
    myvar = i;
}
console.log(new Date().getTime() - startTime);

var startTimx = new Date().getTime();
var myvax;
for (var j=0; j<100000; j++){
var myvax = j;
}
console.log(new Date().getTime() - startTimx);
161
169

第一個測試在 161 毫秒內執行,第二個測試(使用var )用了 169 毫秒來執行。 這是 7 毫秒的差異,在多次運行基准測試后保持一致。

整個基准測試被粘貼到 Chrome JavaScript 控制台中,然后在執行前編譯,這就是為什么第一個輸出不會出現在第一次調用 console.log() 的下方。

自己試試吧!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM