JavaScript 中的 循环(Loops) 和 作用域(Scope) – JavaScript 完全手册(2018版)

10年服务1亿前端开发工程师

小编推荐:掘金是一个面向程序员的高质量技术社区,从 一线大厂经验分享到前端开发最佳实践,无论是入门还是进阶,来掘金你不会错过前端开发的任何一个技术干货。

注:本文为 《 JavaScript 完全手册(2018版) 》第27节,你可以查看该手册的完整目录。

JavaScript 中,和循环与作用域有关的特性可能会给开发人员带来一些麻烦。我们将学习一些关于 循环 和使用 varlet 作用域的技巧。

举个例子:

const operations = []

for (var i = 0; i < 5; i++) {
  operations.push(() => {
    console.log(i)
  })
}

for (const operation of operations) {
  operation()
}

它遍历 5 次,每次为 operations 的数组添加了一个函数。这个函数只是控制台打印循环索引变量 i

稍后运行这些函数。

期望的结果是:

0
1
2
3
4

但实际上打印的是:

5
5
5
5
5

为什么会这样呢? 原因是使用了 var

由于 var 声明被提升,上面的代码等于

var i;
const operations = []

for (i = 0; i < 5; i++) {
  operations.push(() => {
    console.log(i)
  })
}

for (const operation of operations) {
  operation()
}

因此,在 for-of 循环中,i 仍然可见,并且始终等于 5,函数中对 i 的每个引用都将使用这个值。

那么我们应该如何让事情按照我们的意愿运行呢?

最简单的解决方案是使用 let 声明。 在 ES2015 中引入,它们有助于避免 var 声明带来的一些奇怪的事情。

只需将循环变量 var 声明更改为 let 声明即可正常工作:

const operations = []
for (let i = 0; i < 5; i++) {
  operations.push(() => {
    console.log(i)
  })
}
for (const operation of operations) {
  operation()
}

这是输出:

0
1
2
3
4

这怎么可能呢? 这是有效的,因为在每次循环迭代中,每次都会创建一个新变量 i ,并且添加到 operations 数组的每个函数都获得它自己的 i 副本。

请记住,在这种情况下您不能使用 const ,因为在 for 尝试第二次迭代中分配新值时会出现错误。

另一种解决此问题的方法在 ES6 之前的代码中很常见,它被称为立即执行函数表达式(IIFE)。

在这种情况下,您可以包裹整个函数并将 i 绑定到这个函数。 因为通过这种方式你创建了一个立即执行的函数,你可以在这里返回一个新函数,所以我们可以在以后执行它:

const operations = []
for (var i = 0; i < 5; i++) {
  operations.push(((j) => {
    return () => console.log(j)
  })(i))
}
for (const operation of operations) {
  operation()
}

如果你觉得本文对你有帮助,那就请分享给更多的朋友
关注「前端干货精选」加星星,每天都能获取前端干货
赞(0) 打赏
未经允许不得转载:WEB前端开发 » JavaScript 中的 循环(Loops) 和 作用域(Scope) – JavaScript 完全手册(2018版)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

前端开发相关广告投放 更专业 更精准

联系我们

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏