2013-08-27 213 views
43

只是一个关于JavaScript变量范围的简短问题。JavaScript循环变量范围

为什么alert()函数打印的值为i而不是返回undefined

$(document).ready(function() { 
    for(var i = 0; i < 10; i += 1){ 
    } 

    alert("What is 'i'? " + i); 
}); 

我是相当新的JS,而在几乎所有其他语言我已经涉足,在for循环将包含值提到循环,而不是在这种情况下,范围的声明,为什么?

即印刷了What is 'i'? 10'

回答

55

见MDN用于一个for-loop的 “initialization parameters”:

的表达(包括赋值表达式)或变量声明。通常用于初始化计数器变量。这个表达式可以有选择地用var关键字声明新的变量。 这些变量对于循环来说不是本地的,即它们与for循环处于相同的范围。该表达式的结果被丢弃。

47

JavaScript没有块范围,只是函数范围。由于i的初始化在一个函数内,因此该变量可在同一个函数的任何其他位置访问。

MDN

重要:JavaScript没有块范围。用块引入的变量的作用域是包含函数或脚本,并且将它们的设置效果保留在块本身之外。换句话说,块语句不会引入范围。尽管“独立”模块是有效的语法,但您不希望在JavaScript中使用独立模块,因为如果您认为它们在C或Java中执行类似块的操作时,它们不会执行您认为它们的操作。

+0

感谢您的意见:) – BlackBox

+0

这是伟大的可重复性,但扰乱了太阳的java试图建立。 – simonarame

+1

@simonarame然后[Java和JavaScript是不一样的](https://stackoverflow.com/a/245068/3978545)所以这是无关紧要的... – Wolfie

9

与其他语言(例如:Java,C++,C)不同,JavaScript不支持块范围。一旦你在一个循环中声明一个变量或函数中它的作用域是函数体中,如果你做

for(i=0; i<arr.length; i++) { 
    var j=0; 
    // ... 
} 

这里您i成为一个全局变量和j成为当地的函数或脚本,其中环路。

8
for(i=0; i<arr.length; i++) { 
    var j=0; 
    // ... 
} 

这是不正确的,说上述创建一个全局变量i。我相信你应该总是使用var来声明变量(除非你故意想要一个'属性'而不是'变量',这在99.99%的JS编码场景中是不太可能的......)

当分配时省略var一个初始值为i不是创建一个本地变量,甚至是一个全局变量,它为全局对象创建一个属性i(它可能看起来/行为大多像全局变量 - 但它们有一些细微差别)。

更好

是:

var i; 
for(i=0; i<arr.length; i++) { 
    var j=0; 
    // ... 
} 

现在循环使用全局变量i(或函数的局部变量i,如果这个代码将出现在一个函数)

看到更多有关这在what is function of the var keywordvariables vs. properties in Javascript

- 注意,有点令人困惑的是,你可以重新声明一个变量,例如在第二个循环中

for(var i=0; i<9; i++){ 
    document.write('i = ' + i + '<br>'); 
} 


for(var i=0; i<9; i++){ 
    document.write('i = ' + i + '<br>'); 
} 

这似乎是有效的(当我测试时没有错误)。您似乎可以用JavaScript重新声明变量 - 但它可能不是每个好主意,除非特殊情况 - 请参阅这个相关问题,提及Google Analytics如何使用'安全'重新声明变量]( Redeclaring a javascript variable

有关于JS(在此相关的SO问题重新声明变量和像i也是循环变量)的一些讨论:declare variables inside or outside the loop

有事件JavaScript pattern for single declaration of variables

14

JavaScript的人正在试图解决这个问题!

EcmaScript6(又名EcmaScript 2015)是去年夏天推出的JavaScript的最新版本,浏览器刚刚开始支持其功能。

其中一个功能是使用“let”表达式的块范围局部变量。截至目前(2016年4月),除Safari之外,大多数主流浏览器都支持这个版本。很少有移动浏览器支持这一点。

你可以阅读更多关于它在这里(特别是,请参阅“让范围的变量for循环”): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

您可以查看当前浏览器的支持这里(寻找行绑定 - >让): https://kangax.github.io/compat-table/es6/

+0

更新您的答案与更多信息。规范是官方的。谢谢 –