【翻译】JavaScript循环和作用域
我的翻译小站:https://www.zcfy.cc/article/javascript-loops-and-scope
翻译原文链接:https://flaviocopes.com/javascript-loops-and-scope/
JavaScript有一个特点,也许会让开发者头痛, 是与循环和作用域相关的.
举个例子:
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在第二次循环时, 尝试赋新值报错。
另外一个非常普遍的解决这个问题是使用pre-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()
}
【翻译】JavaScript循环和作用域的更多相关文章
- 【翻译】JavaScript中的作用域和声明提前
原文:http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html ===翻译开始=== 你知道下面的JavaScript脚本执 ...
- javascript(面向对象,作用域,闭包,设计模式等)
javascript(面向对象,作用域,闭包,设计模式等) 1. 常用js类定义的方法有哪些? 参考答案:主要有构造函数原型和对象创建两种方法.原型法是通用老方法,对象创建是ES5推荐使用的方法.目前 ...
- 认识javascript中的作用域和上下文
javascript中的作用域(scope)和上下文(context)是这门语言的独到之处,这部分归功于他们带来的灵活性.每个函数有不同的变量上下文和作用域.这些概念是javascript中一些强大的 ...
- Javascript之变量作用域
分析: 无论是强类型语言c#.c++.java等语言,还是弱类型语言如Javascript,所有变量可以抽象为两种类型,即局部变量和全局变量. 全局变量:整个作用域可见. 局部变量:局部可见,退出作用 ...
- 深入理解 JavaScript 变量的作用域和作用域链
一个变量的作用域(scope)是程序源代码中定义这个变量的区域.简单的说,作用域就是变量与函数的可访问范围.全局变量拥有全局作用域,在JavaScript代码中的任何地方都有定义.局部变量是在函数体内 ...
- javascript篇-----函数作用域,函数作用域链和声明提前
在一些类似C语言的编程语言中,花括号内的每一段代码都具有各自的作用域,而且变量在声明它们的代码段之外是不可见的(也就是我们不能在代码段外直接访问代码段内声明的变量),我们称之为块级作用域,然而,不同于 ...
- JavaScript之函数作用域
有过类似C语言编程经验的同学应该都知道“块级作用域(block scope)”:花括号内的每一段代码都具有各自的作用域,而且在声明它们的代码段之外是不可见的.而在JavaScript中是没有块级作用域 ...
- JavaScript中的作用域和声明提前
[翻译]JavaScript中的作用域和声明提前 原文:http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html ===翻译 ...
- JavaScript函数变量作用域
变量作用域 在JavaScript中,用var申明的变量实际上是有作用域的. 如果一个变量在函数体内部申明,则该变量的作用域为整个函数体,在函数体外不可引用该变量. 如果两个不同的函数各自申明了同一变 ...
随机推荐
- htop工具使用
1 防止进程重复显示 在使用htop查看进程信息的时候,经常会出现很多个进程重复的情况,如下情况: 经研究发现,htop会把一个进程里的线程当做一个进程来显示出来,上图中的java进程有多个线程,所以 ...
- pandas 语句
1.对于时间格式数据的处理 有些时候time_stamp是object格式,提取相应的日期,小时,星期等: 方法1 from datetime import datetime user_trad[ ...
- (转)新手C#SQL语句的学习2018.08.13
1.创建数据库(create) CREATE DATABASE database-name 2.删除数据库(drop) drop database dbname 3.备份数据库 --- 创建 备份数据 ...
- Eletron 打开文件夹,截图
1.shell.openItem(fullPath) var fullpath = path.join(processPath)+Math.random()+".png"; she ...
- Retrofit2+Rxjava2 okhttp RxBus 使用记录
学习 博客 http://blog.csdn.net/r17171709/article/details/51149350 @Query 后面跟要添加的字段 @Path 连接url里面{userId} ...
- np.random.randn()、np.random.rand()、np.random.randint()
(1)np.random.randn()函数 语法: np.random.randn(d0,d1,d2……dn) 1)当函数括号内没有参数时,则返回一个浮点数: 2)当函数括号内有一个参数时,则返回秩 ...
- Princess Principal(思维题)
Princess Principal https://www.nowcoder.com/acm/contest/201/J 题目描述 阿尔比恩王国(the Albion Kingdom)潜伏着一群代号 ...
- python之socket运用之传输大文件
socket建议最大的传输单元是8192个字符,但是如果超过8192就会出现问题,我们可以用下面的方法处理 客户端代码 import subprocess import socket ip_bind ...
- Python requests 使用心得
最近在用requests写一些项目,遇见了一些问题,百度了很多,有些都不太好使,最后看了下requestsAPI文档,才明白了很多,最后项目趋于稳定.看来学东西还是API文档比较权威啊~ 问题场景 项 ...
- swift UICollectionView使用
方法1:创建 的时候注册 layout /// 时间view private lazy var timeCollectionV: UICollectionView = { 1.直接注册 并设置好 UI ...