当前位置:网站首页>闭包(五)----一个常见的循环
闭包(五)----一个常见的循环
2022-07-31 05:10:00 【F班的小夏同学】
function foo(){
var arr = [];
for(var i = 0; i < 2; i++){
arr[i] = function(){
return i;
}
}
return arr;
}
var bar = foo();
console.log(bar[0]());//2
以上的代码运行结果是2,而不是预想的0。接下来我们用执行环境图示的方法,来看看到底是哪里出了问题。
执行流首先创建并进入全局执行环境,进行声明提升过程。执行流执行到第10行的时候,创建并进入foo()函数执行环境,并进行声明提升。然后执行第2行,将arr赋值为[]。然后执行第3行,给arr[0]和arr[1]都赋值为一个匿名函数。然后执行第8行,以arr的值为返回值退出函数。由于此时有闭包的存在,所以foo()执行环境并不会被销毁。
执行流进入全局执行环境,继续执行第10行,将函数的返回值arr赋值给bar
执行流执行第11行,访问bar的第0个元素并执行。此时,执行流创建并进入匿名函数执行环境,匿名函数中存在自由变量i,需要使用其作用域链匿名函数 -> foo()函数 -> 全局作用域进行查找,最终在foo()函数的作用域找到了i,然后在foo()函数的执行环境中找到了i的值2,于是给i赋值2
执行流接着执行第5行,以i的值2作为返回值返回。同时销毁匿名函数的执行环境。执行流进入全局执行环境,接着执行第11行,调用内部对象console,并找到其方法log,将bar0的值2作为参数放入该方法中,最终在控制台显示2
由此我们看出,犯错原因是在循环的过程中,并没有把函数的返回值赋值给数组元素,而仅仅是把函数赋值给了数组元素。这就使得在调用匿名函数时,通过作用域找到的执行环境中储存的变量的值已经不是循环时的瞬时索引值,而是循环执行完毕之后的索引值
IIFE
由此,可以利用IIFE传参和闭包来创建多个执行环境来保存循环时各个状态的索引值。因为函数传参是按值传递的,不同传参的函数被调用时,会创建不同的执行环境。
function foo(){
var arr=[];
for(var i=0;i<2;i++){
arr[i]=(function fn(j){
return funtion test(){
return j;
}
})(i)
}
}

块级作用域
使用IIFE还是较为复杂,使用块级作用域则更为方便
由于块作用域可以将索引值重新绑定到了循环的每一个迭代中,确保使用上一个循环迭代结束时的值重新进行赋值,相当于为每一次索引值都创建一个执行环境。
function foo(){
var arr=[];
for(let i=0;i<2;i++){
arr[i]=function(){
return i;
}
}
return arr;
}
var bar=foo();
console.log(bar[0]());//0
边栏推荐
- C语言教程(二)-printf及c自带的数据类型
- Redis Advanced - Cache Issues: Consistency, Penetration, Penetration, Avalanche, Pollution, etc.
- 1D, 2D, 3D convolution operations in pytorch
- uni-app进阶之创建组件/原生渲染【day9】
- The interviewer asked me TCP three handshake and four wave, I really
- 剑指offer基础版--- 第23天
- 【MySQL8入门到精通】基础篇- Linux系统静默安装MySQL,跨版本升级
- C语言文件读、写、定位函数
- Element concatenation operations in numpy and pytorch: stack, concatenat, cat
- wx.miniProgram.navigateTo在web-view中跳回小程序并传参
猜你喜欢

剑指offer基础版 ----- 第28天

Tapdata 与 Apache Doris 完成兼容性互认证,共建新一代数据架构

MySQL8.0安装教程,在Linux环境安装MySQL8.0教程,最新教程 超详细

Goodbye to the cumbersome Excel, mastering data analysis and processing technology depends on it
![[MQ I can speak for an hour]](/img/ef/863c994ac3a7de157bd39545218558.jpg)
[MQ I can speak for an hour]

【C语言3个基本结构详解——顺序、选择、循环】

MySQL8.0.26安装配置教程(windows 64位)

剑指offer专项突击版 ---第 5 天

Distributed Transactions - Introduction to Distributed Transactions, Distributed Transaction Framework Seata (AT Mode, Tcc Mode, Tcc Vs AT), Distributed Transactions - MQ

账号或密码多次输入错误,进行账号封禁
随机推荐
C语言指针详解
C语言实验五 循环结构程序设计(二)
快速掌握并发编程 --- 基础篇
剑指offer基础版 ---- 第27天
数据库上机实验7 数据库设计
TOGAF之架构标准规范(一)
第7章 网络层第3次练习题答案(第三版)
基于web3.0使用钱包Metamask的三方登陆
第7章 网络层第1次练习题答案(第三版)
MySQL(更新中)
Minio upload file ssl certificate is not trusted
Redis first meeting
Temporal线上部署
MySQL-Explain详解
Simple command of mysql
MySQL8.0.26安装配置教程(windows 64位)
Redis Advanced - Cache Issues: Consistency, Penetration, Penetration, Avalanche, Pollution, etc.
If the account number or password is entered incorrectly for many times, the account will be banned.
面试官:生成订单30分钟未支付,则自动取消,该怎么实现?
Distributed Transactions - Introduction to Distributed Transactions, Distributed Transaction Framework Seata (AT Mode, Tcc Mode, Tcc Vs AT), Distributed Transactions - MQ