【翻译】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申明的变量实际上是有作用域的. 如果一个变量在函数体内部申明,则该变量的作用域为整个函数体,在函数体外不可引用该变量. 如果两个不同的函数各自申明了同一变 ...
随机推荐
- Jstl标签<c:forEach>的用法
<c:forEach>除了支持数组之外,还有标准J2SE的集合类型,例如:ArrayList.List.LinkedList.Vector.Stack和Set 等等:另外还包括java.u ...
- TEXT 3 Food firms and fat-fighters
TEXT 3 Food firms and fat-fighters 食品公司与减肥斗士 Feb 9th 2006 From The Economist Global Agenda Five lead ...
- 利用Spark-mllab进行聚类,分类,回归分析的代码实现(python)
Spark作为一种开源集群计算环境,具有分布式的快速数据处理能力.而Spark中的Mllib定义了各种各样用于机器学习的数据结构以及算法.Python具有Spark的API.需要注意的是,Spark中 ...
- Chi-Square Statistic/Distribution
. 1.What is a Chi Square Test? 卡方检验有两种类型.两者使用卡方统计量和分布的目的不同. 第一种:卡方拟合优度检验确定样本数据是否与总体匹配.(这里不介绍) 第二种:独立 ...
- azkaban编译安装配置文档
azkaban编译安装配置文档 参考官方文档: http://azkaban.github.io/azkaban/docs/latest/ azkaban的配置文件说明:http://azkaban. ...
- golang 打印变量类型
fmt.Println("type:", reflect.TypeOf(err.Error()))
- 64位tomcat不能配32位的JDK使用
警告: The APR based Apache Tomcat Native library failed to load. The error reported was [D:\apache-tom ...
- httplib:AttributeError: 'module' object has no attribute 'HTTPConnection'
# -*-coding:gb2312-*- #Function:学习python的httplib模块 import httplib conn = httplib.HTTPConnection(&quo ...
- memcache简单操作
<?php $m = new Memcache(); $m->connect('localhost',11211); //获取版本 echo "server's version: ...
- Spring框架的AOP技术之通知类型
1. 通知类型 * @Before -- 前置通知 * @AfterReturing -- 后置通知 * @Around -- 环绕通知(目标对象方法默认不执行的,需要手动执行) * @After - ...