繁体   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