- 前言
- 关于 ECMASCRIPT 发展史和现状
- ES6 带来的重大特性
- ES2016(ES7)的改进
- ES2017(ES8)带来的重大新特性
- ES2018(ES9)带来的重大新特性
- JavaScript 编码风格指南
- JavaScript 词法结构(构建块)
- JavaScript 变量
- JavaScript 数据类型
- JavaScript 表达式
- 原型继承
- 如何使用 JavaScript 中的 Classes(类)
- JavaScript 异常处理
- JavaScript 中的分号(;)
- JavaScript 中的引号
- JavaScript 字面量模板(Template Literals)指南
- JavaScript 中的 function(函数)
- JavaScript 箭头函数(Arrow Function)
- JavaScript 中的闭包(Closures)
- JavaScript 数组(Arrays)
- JavaScript 中的循环(Loops)
- JavaScript 中的事件(Events)
- JavaScript 中的事件循环(Event Loop)
- JavaScript 异步编程和回调
- 理解 JavaScript 中的 Promises
- 用 async 和 await 编写现代 JavaScript 异步代码
- JavaScript 中的 循环(Loops) 和 作用域(Scope)
- JavaScript 定时器 setTimeout() 和 setInterval()
- JavaScript 中的 this
- JavaScript 严格模式(Strict Mode)
- JavaScript 中的 立即执行函数表达式(IIFE)
- JavaScript 中的数学运算符
- JavaScript 中的 Math 对象
- 介绍 ES Modules(模块)
- 介绍 CommonJS
- JavaScript 术语表
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
JavaScript 中的 循环(Loops) 和 作用域(Scope)
JavaScript 中,和循环与作用域有关的特性可能会给开发人员带来一些麻烦。我们将学习一些关于 循环 和使用 var
和 let
作用域的技巧。
举个例子:
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() }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论