循环中的闭包
来源:互联网 发布:fresh玫瑰化妆水知乎 编辑:程序博客网 时间:2024/06/05 00:40
首先看一段JS代码
function F(){ var arr =[],i; for(i=0;i<3;i++){ arr[i] = function(){ return i; } } return arr;}在控制器中执行>var arr = F()>arr[0]()>arr[1]()>arr[2]()
当我们看到这里的时候肯定会觉得这输出的不就是每次循环i的值么,但是我们在控制台里面运行后的结果如下
我们发现结果并不是我们想的那样简单,而是所有的值都为3了
这就是JavaScript中常见的闭包的作用
原因分析:
我们创建了一个函数F对象,里面有数组arr和一个局部变量i,执行for循环,定义arr数组里面的每个元素为一个函数对象,函数返回值为局部变量i的值,函数对外部闭包域的私有变量进行了引用,故 每个arr[]对象的 function scope 会产生一个名为 closure 的对象属性,closure 对象内含有一个名为 i 的引用,当执行F()时,实际上i的值已经变成了3,当执行arr时,每个函数里面的i是对局部变量i的引用,而此时的i已经变了所以引用的i的值全是3而不是对应的预期的值
我在搜索js闭包问题时,看到segmentfault上有位朋友讲了9种解决办法,觉得很有启发,就看着能不能举一反三,根据他的思路解决我们的这个问题,
具体的链接为多种方法解决循环中的闭包问题
解决办法
方法一
我在下面的for循环里面增加了一个闭包域空间,用arg来保存传进来的i,只要arg不变那么return 的就是相对应的值
function F(){ var arr =[],i; for(i=0;i<3;i++){ (function(arg){ arr[i] = function(){ return arg; } }(i)) } return arr;}var arr = F();arr[1]()
方法二
这种方法和第一种有些类似,但又不同
不同点:解决办法一是在新增的匿名闭包空间内完成数组的函数绑定,而此例是将返回函数在新增的匿名函数返回的函数上 此时绑定的函数中的 function scope 中的 closure 对象的 引用 arg 是指向将其返回的匿名函数的私有变量 arg
function F(){ var arr =[],i; for(i=0;i<3;i++){ arr[i] = (function(arg){ return function(){ return arg; }; }(i)) } return arr;}var arr = F();arr[1]()
方法三
这种方法和第一种相似,都是新增了一个闭包域,返回的是新的闭包域中的私有变量
function F(){ var arr =[],i; for(i=0;i<3;i++){ (function(){ var temp = i; arr[i] = function(){ return temp; } }()) } return arr;}var arr = F();arr[1]()
方法四
function F(){ var arr =[],i; for(i=0;i<3;i++){ arr[i] = (function(){ var temp = i; return function(){ return temp; } }()) } return arr;}var arr = F();arr[1]()
方法五
function F(){ var arr =[],i; for(i=0;i<3;i++){ (arr[i] = function(){ return(arguments.callee.i); }).i = i; } return arr;}var arr = F();arr[1]()
方法六
这种办法是给每个数组对象 new一个function对象,每个对象都有自己的作用域,通过 new 使用 Function 的构造函数 创建 Function 实例实现,由于传入的函数体的内容是字符串,所以Function 得到的是一个字符串拷贝,而没有得到 i 的引用(这里是先获取 i.toString()然后与前后字符串拼接成一个新的字符串,Function 对其进行反向解析成 JS 代码)
function F(){ var arr =[],i; for(i=0;i<3;i++){ arr[i] = new Function("return "+i); } return arr;}var arr = F();arr[1]()
方法七
这里和上面的一种办法和大的区别就是上一种办法使用了new关键字,结果是Function()函数作为了构造器函数
而这里没有new关键字,则是将Function()作为了一个函数进行调用,然后再函数内部自己生产了一个实例进行返回
function F(){ var arr =[],i; for(i=0;i<3;i++){ arr[i] = Function("return "+i); } return arr;}var arr = F();arr[1]()
- 循环中的闭包
- 循环中的闭包
- 循环中的闭包
- 循环中的闭包
- 循环中的闭包
- 循环中的闭包
- JavaScript闭包中的循环
- js for循环中的闭包
- js for循环中的闭包
- Swift 中的闭包循环引用
- swift 闭包引用循环中的迷魂阵
- JavaScript闭包中的循环(二)
- for循环中的闭包问题及解决方案
- 循环中的闭包,怎么返回当前索引
- js 解决js for 循环中的闭包问题
- 循环和闭包
- JavaScript 闭包 for循环
- 循环中使用闭包
- 面试:数组:数组配对
- IMF传奇行动第86课:Spark Streaming第五课:Spark Streaming数据源Flume实际案例分享
- [A* K短路 || 可持久化堆] POJ 2449 Remmarguts' Date
- Matlab——filter函数和butter函数
- BLE 读取characteristic时,为什么没有 'BLE_GATTS_EVT_READ' ?
- 循环中的闭包
- 台湾印象: 国境以南
- 设计模式总结
- 单链表的反转
- 台湾印象: 太平洋的风
- swift开发网络篇 - 用户登录POST JSON and header
- 台湾印象: 淡水河畔
- 第2章 线程安全性
- 牛客网错题本之JAVA_第三期