循环中的闭包
来源:互联网 发布:手机电影拍摄软件 编辑:程序博客网 时间:2024/06/07 12:28
function F(){ var arr = [],i; for(i = 0;i < 3;i++){ arr[i] = function(){ return i; }; } return arr;}var arr = F();
上述for
循环每迭代一次就创建一个arr
的项,每一项中保存着一个函数,该函数返回当前作用域中的i
的变量值,然后在F()
中返回该数组,将该函数赋值就可以访问F()
内部非变量,因此形成了一个闭包
执行arr[0](),arr[1](),arr[2]()
查看结果的时候发现结果并不是我们想象的0,1,2
arr[0]();3arr[1]();3arr[2]();3
原因:在for
循环中创建了三个闭包,而它们都指向了一个局部变量i
。但是,闭包并不会记录它们的值,它们所拥有的只是相关域在创建时的一个链接(即引用)。在这个列子中,变量i
存在于定义这三个函数域中。对这三个函数中的任何一个而言,当要去获取某个变量时,它会从其所在的域开始逐级寻找那个距离最近的i
的值。由于循环结束时i
的值为3,所以这三个函数都指向了这个值
换句话说就是:for
循环一次创建一个对i
变量引用的闭包,但是闭包中不会保存当时的值,而只是一个对于i
变量的引用,调用引用的值会随着本身的值得变化而变化,当调用三个函数时会逐级寻找最近的i
的值,此时i
的值为3
改正
换一种闭包的形式
function F(){ var arr = [],i; for(i = 0;i < 3;i++){ arr[i] = (function(x){ return function(){ return x; } } )(i); } return arr;}var arr = F();
结果:
arr[0]();0arr[1]();1arr[2]();2
在这里,不再创建直接返回i
的函数,而是将i
传递给另一个即时函数。在该函数中,i
被赋值给了局部变量x
,这样一来,每次迭代中的x
就会是不同的值了
下面的形式也可以:
function F(){ var arr = [],i; for(i = 0;i < 3;i++){ (function(j){ arr[j] = function(){ return j; }; })(i); } return arr;}var arr = F();arr[0]();0arr[1]();1arr[2]();2
也可以不使用即时函数,而定义一个内部函数来实现相同的功能,要点是在每次迭代操作中,我们要在中间函数内将i
的值”本地化”而不是当前作用域中的值
function F(){ var arr = [],i; function binder(x){ return function(){ return x; }; } for(i = 0;i < 3;i++){ arr[i] = binder(i); } return arr;}var arr = F();arr[0]();0arr[1]();1arr[2]();2
若在内部函数中不将其本地化,则结果还是为3
function F(){ var arr = [],i; function binder(){ return function(){ return i; }; } for(i = 0;i < 3;i++){ arr[i] = binder(); } return arr;}var arr = F();arr[0]();3
但是只要有参数传入内部函数binder()
,就不会再F()
的作用域中寻找i
,会首先在函数作用域中寻找
function F(){ var arr = [],i; function binder(i){ return function(){ return i; }; } for(i = 0;i < 3;i++){ arr[i] = binder(i); } return arr;}var arr = F();arr[0]();0
参考:《JavaScript面向对象编程指南》
0 0
- 循环中的闭包
- 循环中的闭包
- 循环中的闭包
- 循环中的闭包
- 循环中的闭包
- 循环中的闭包
- JavaScript闭包中的循环
- js for循环中的闭包
- js for循环中的闭包
- Swift 中的闭包循环引用
- swift 闭包引用循环中的迷魂阵
- JavaScript闭包中的循环(二)
- for循环中的闭包问题及解决方案
- 循环中的闭包,怎么返回当前索引
- js 解决js for 循环中的闭包问题
- 循环和闭包
- JavaScript 闭包 for循环
- 循环中使用闭包
- 同步(Synchronous)/异步(Asynchronous)
- 附录A:Windows编程入门
- php,java实现抽象工厂模式
- java基础学习(五)访问权限控制
- 基于XMPP协议(openfire服务器)的消息推送实现
- 循环中的闭包
- Poweroj 1194(dp背包问题)
- A Boring Game
- Openfire 用户离线、断线 及心跳检测
- Hadoop组件配置
- 通过netcraft查询一个网站的服务信息
- 我的程序员之路(英语的学习)
- IONIC 自动更新APP版本
- Python自动运维系列:每天凌晨定时执行特定任务