JavaScript 变量如何工作?

发布于 2024-12-12 13:27:38 字数 536 浏览 0 评论 0原文

我知道 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;
}

这样,为什么?

I know that JavaScript vars point to a value:

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

So in that example I've changed foo pointing to true -> foo pointing to false, but if I do:

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

Am I creating a new var for each iteration?

Is there any difference in the following two ways of doing the same?

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

and

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

If so, why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

滥情哥ㄟ 2024-12-19 13:27:38

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
        })();
    }
}

Update 2015 年。 ES6(或有时称为 ES2015)提供了 let 声明,该声明确实提供了块作用域。在这种情况下,let 变量声明仅提升到当前块作用域的顶部。截至 2015 年中期,该功能尚未在浏览器中广泛实现,但即将推出,并且可以在 Node.js 等服务器端环境中或通过转译器使用。

因此,在 ES6 中,如果您这样做:

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

isomeVar 都将仅在循环中是本地的。

There is no block scope in Javascript ES5 and earlier, only function scope. Furthermore, the declarations of all javascript variables declared within a function scope are automatically "hoisted" to the top of the function.

So, declaring a variable within a loop isn't doing anything different than declaring it at the top of the function and then referencing it within the loop.

See these two references for some useful explanation: http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting and http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-javascript-hoisting-explained/.

Note: the assignment to a variable is not hoisted, just the declaration of the variable. So, if you do this:

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

It works like this:

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

If you wanted to create a new scope inside your for loop, you could use an IIFE (immediately invoked function expression) like this:

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
        })();
    }
}

Update in 2015. ES6 (or sometimes called ES2015) offers the let declaration which does offer block scope. In that case a let variable declaration is hoisted only to the top of the current block scope. As of mid 2015, this is not yet widely implemented in browsers, but is coming soon and it is available in server-side environments like node.js or via transpilers.

So, in ES6 if you did this:

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

Both i and someVar would be local to the loop only.

み零 2024-12-19 13:27:38

不,没有什么区别;在 JavaScript 中,变量的作用域是函数级别,而不是块级别。

No, there is no difference; in JavaScript, variables are scoped on the function level, not the block level.

霊感 2024-12-19 13:27:38

JSLint 这样的工具建议您将所有 var 语句放在函数的顶部。这是因为如果您不这样做,JavaScript 本质上会为您做这件事,所以如果您这样做,也不会那么混乱。在您的示例中,将 var 放在何处并不重要,只要它出现在 myvar 的一个定义之前即可。同样,您也可以在函数顶部声明i

更有趣的是分层的作用域链,JavaScript 在需要查找名称时会在其中搜索名称。它从本地全局搜索作用域链,直到找到所述名称的第一个实例。

这就是为什么你可以玩这样的游戏来惹恼你的朋友:

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

foofinder();
>>> "beers"

Tools like JSLint recommend that you put all your var statements at the top of functions. It's because JavaScript essentially does it for you if you don't, so it's less confusing if you do. In your example, it doesn't matter where you put var as long as it occurs before one definition of myvar. Likewise, you may as well declare i at the top of the function as well.

What's more interesting is the hierarchical scope chain in which JavaScript searches for names when it wants to look one up. It searches up the scope chain from local to global until it finds the first instance of said name.

Which is why you can play games like this to annoy your friends:

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

foofinder();
>>> "beers"
月亮邮递员 2024-12-19 13:27:38

正如 @icktoofay 所说,在 javascript 中没有区别。在某些语言中,在每次迭代时,变量都会被实例化,然后超出范围,并被垃圾收集。

要在 javascript 中模拟这一点,您可以这样做:

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

在这种情况下,myvar 仅存在于匿名函数的范围内,因此在每次迭代时,都会创建一个新的 myvar 实例。

As @icktoofay said, in javascript there is no difference. In some languages, at each iteration, the variable will be instantiated, then go out of scope, and left to be garbage collected.

To simulate this in javascript, you could do:

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

In this case, myvar only exist in the scope of the anonymous function, so at each iteration, a new instance of myvar is created.

作死小能手 2024-12-19 13:27:38

通过在变量名之前不断声明 var,您可以指示 JavaScript 引擎或解释器将变量重新初始化为未定义的值(undefined 而不是数字,字符串/文本、布尔值或 null) 之前的赋值,这将是额外的指令,减慢循环执行的速度。您还增加了代码大小并降低了解析/解释/编译代码的速度。

对于几乎任何应用程序,都不存在功能差异,但仍然存在差异,并且在执行数十万或数十亿次循环后,差异可能会很明显。但是,在函数中重复使用相同名称的 VAR 声明会在 Chrome / V8 中导致致命异常。

更新:在变量名称之前使用 var 明显比省略 var 慢,如使用 JavaScript 控制台在 Chrome / v8 上运行的以下基准测试所示。

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() 的下方。

自己尝试一下吧!

By constantly declaring var before the variable name, you could be instructing the JavaScript engine or interpreter to re-initialize the variable to an undefined value (undefined as opposed to a number, string/text, boolean value, or null) before assignment, which would be extra instructions, slowing down the speed of loop execution. You're also inflating code size and reducing the speed at which the code is parsed/interpreted/compiled.

For virtually any application, there is no functional difference, but there still is one and the difference might be noticeable after hundreds of thousands or billions of loop executions. However, repeated VAR declarations of the same name within a function leads to fatal exceptions in Chrome / V8.

UPDATE: Using var before the variable name is provably slower than omitting var as demonstrated by the following benchmark run on Chrome / v8 with the JavaScript console.

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

The first test executed in 161 ms and the second test (with var) took 169 ms to execute. That's a difference of 7 ms, consistent after multiple runs of the benchmark.

The entire benchmark was pasted into the Chrome JavaScript console and then compiled before its execution, which is why the first output does not appear below the first call to console.log().

Try it yourself!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文