JavaScript: 在块级作用域中本地化变量

5

我试图理解JavaScript中的变量作用域。以下是我的做法:

<script>
for (var i = 0; i < 3; i++) {
  document.getElementById(i).onclick = function() {
    console.log(i);
  }
}
</script>

输出结果始终为3,我理解这是因为i已经被引用保留了。如何将i本地化,以便可以记录递增的值?
谢谢!
更新
感谢大家的快速和不错的回应。这些解决方案确实很有帮助!
最初,我尝试了与@GrailsGuy类似的方法,在此提供代码:
<script>
for (var i = 1; i <= 3; i++) {
    document.getElementById(i).onclick = function() {
        console.log(logCall(i));
    }
}
function logCall(i) {
    return i;
}
</script>

但是看起来 i 没有被本地化。无法确定原因!

这与onclick事件有关吗?如果用户只点击一次,它如何通过onclick循环?你需要logCall()函数吗?那不就跟console.log(i)一样吗? - oobie11
关于您的编辑,它与您的第一个示例中的问题相同。无论您在事件处理程序内使用 console.log(i) 还是 superlongandconfusingfunctionname(i),都没有任何区别。您正在尝试在循环终止后访问 i - Felix Kling
2个回答

7
创建新的作用域。
for (var i = 0; i < 3; i++) {
  (function(i) {
    document.getElementById(i).onclick = function() {
      console.log(i);
    }
  }(i));
}

2

Javascript中,作用域不是由括号创建的(与类C语言语法相反)。但是作用域确实是在函数中创建的,因此一种方法是将调用提取到一个函数中(已更新):

<script>
for (var i = 0; i < 3; i++) {
    logCall(i);
}

function logCall(i) {
    document.getElementById(i).onclick = function() {
        console.log(i);
    }
}
</script>

这样做的额外好处是使代码更具可重用性。

我没有给你的代码点踩,但它并不能解决问题。 - Prinzhorn
1
这是错误的,http://jsfiddle.net/GaCPv/ - Musa
5
这不起作用。点击处理程序中的“i”与之前相同。console.log也是一个函数,按照你的逻辑,它最初应该也可以工作。 - poke
抱歉,我正在输入一份更长的解释,没有注意到我没有提取足够的逻辑。现在应该可以工作了。 - Igor
这并不一定与块作用域有关,而是与JS中闭包的工作方式有关。如果当前环境中变量的值被复制到新环境中,而不仅仅是链接它们,那么即使没有块作用域,它也可以正常工作。 - Felix Kling
@FelixKling 是的,说得好。我提到它是“单向”的,因为我通常更喜欢这样做,因为你通常可以找到重用函数的方法。 - Igor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接