JS中for循环里面的闭包问题的原因及解决办法
2018-01-23 01:42
405 查看
我们先看一个正常的for循环,普通函数里面有一个for循环,for循环结束后最终返回结果数组
有时我们需要在for循环里面添加一个匿名函数来实现更多功能,看下面代码
上面这段代码就形成了一个闭包:
闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见的方式,就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。
在for循环里面的匿名函数执行 return i 语句的时候,由于匿名函数里面没有i这个变量,所以这个i他要从父级函数中寻找i,而父级函数中的i在for循环中,当找到这个i的时候,是for循环完毕的i,也就是5,所以这个box得到的是一个数组[5,5,5,5,5]。
解决方案1
在看解决方案一之前,我们先看一下匿名函数的自我执行:
匿名函数自我执行的写法是,在函数体外面加一对圆括号,形成一个表达式,在圆括号后面再加一个圆括号,里面可传入参数。
例如下代码:
我们再来看解决方案1:
通过给匿名函数传参,而传递的这个参数i是每次执行for循环里面的i,每次传递的参数i的值都不一样,匿名函数里面的num接收传递的参数i,所以box()最终输出结果为[0,1,2,3,4]
解决方案2
这种方案的原理就是在匿名函数1里面再写入一个匿名函数2,这个匿名函数2需要的num值会在他的父级函数匿名函数1里面去寻找,而匿名函数1里面的num值就是传入的这个参数i,和上面例子中的i是一样的,
box()最终返回结果[0,1,2,3,4],
解决方案3
如果将一个匿名函数自我执行的时候赋值给一个变量,那么这个匿名函数中的圆括号的可以去掉的,看下面代码,
利用匿名函数的这一特点,我们可以将解决方案1中的代码改进一下:
匿名函数在执行的时候他本身就传递给了一个变量arr[i],所以匿名函数的圆括号是可以去掉的。
function box(){ var arr = []; for(var i=0;i<5;i++){ arr[i] = i; } return arr; } alert(box()) //正常情况不需要闭包,就可以达到预期效果,输出结果为一个数组0,1,2,3,4
有时我们需要在for循环里面添加一个匿名函数来实现更多功能,看下面代码
//循环里面包含闭包函数 function box(){ var arr = []; for(var i=0;i<5;i++){ arr[i] = function(){ return i; //由于这个闭包的关系,他是循环完毕之后才返回,最终结果是4++是5 } //这个匿名函数里面根本没有i这个变量,所以匿名函数会从父级函数中去找i, } //当找到这个i的时候,for循环已经循环完毕了,所以最终会返回5 return arr; } //alert(box()); //执行5次匿名函数本身 //alert(box()[1]); //执行第2个匿名函数本身 //alert(box().length); //最终返回的是一个数组,数组的长度为5 alert(box()[0]()); //数组中的第一个数返回的是5,这是为什么?
上面这段代码就形成了一个闭包:
闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见的方式,就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。
在for循环里面的匿名函数执行 return i 语句的时候,由于匿名函数里面没有i这个变量,所以这个i他要从父级函数中寻找i,而父级函数中的i在for循环中,当找到这个i的时候,是for循环完毕的i,也就是5,所以这个box得到的是一个数组[5,5,5,5,5]。
解决方案1
在看解决方案一之前,我们先看一下匿名函数的自我执行:
匿名函数自我执行的写法是,在函数体外面加一对圆括号,形成一个表达式,在圆括号后面再加一个圆括号,里面可传入参数。
例如下代码:
(function(){ alert('lee'); //匿名函数自我执行(匿名函数)() })();
我们再来看解决方案1:
function box(){ var arr = []; for(var i=0;i<5;i++){ arr[i] = (function(num){ //自我执行,并传参(将匿名函数形成一个表达式)(传递一个参数) return num; //这里的num写什么都可以 })(i); //这时候这个括号里面的i和上面arr[i]的值是一样的都是取自for循环里面的i } return arr; } //alert(box()); //alert(box()[1]); //alert(box().length); alert(box()[0]);
通过给匿名函数传参,而传递的这个参数i是每次执行for循环里面的i,每次传递的参数i的值都不一样,匿名函数里面的num接收传递的参数i,所以box()最终输出结果为[0,1,2,3,4]
解决方案2
这种方案的原理就是在匿名函数1里面再写入一个匿名函数2,这个匿名函数2需要的num值会在他的父级函数匿名函数1里面去寻找,而匿名函数1里面的num值就是传入的这个参数i,和上面例子中的i是一样的,
function box(){ var arr = []; for(var i=0;i<5;i++){ arr[i] = (function(num){ //num在这里 //原理和上面一种方法一样的,所以可以实现闭包 return function(){ //在这个闭包里面再写一个匿名函数 return num; }; })(i) } return arr; } //alert(box()); //alert(box()[1]); //alert(box().length); var b = box(); alert(b[0]()); alert(box()[0]());
box()最终返回结果[0,1,2,3,4],
解决方案3
如果将一个匿名函数自我执行的时候赋值给一个变量,那么这个匿名函数中的圆括号的可以去掉的,看下面代码,
var tip = function(){ //这样把匿名函数自我执行的时候赋值给一个变量,那么圆括号是可以去掉的 alert('lee'); }();
利用匿名函数的这一特点,我们可以将解决方案1中的代码改进一下:
function box(){ var arr = []; for(var i=0;i<5;i++){ arr[i] = function(num){ return num; }(i); } return arr; } //alert(box()); //alert(box()[1]); //alert(box().length); alert(box()[4]);
匿名函数在执行的时候他本身就传递给了一个变量arr[i],所以匿名函数的圆括号是可以去掉的。
相关文章推荐
- JS中for循环里面的闭包问题的原因及解决办法
- JS中使用for循环添加点击事件时,获取i值及参数异常原因及解决办法
- 20140921遇到的问题-----JAVA----JS------jquery-1.11.1.min.js找不到的原因和解决办法
- Struts2初学devMode发展模式,更改action出现映射错误解决办法(原因是版本问题,轻松解决)
- UTF-8编码主页调用JS显示乱码问题解决办法
- IIS发生意外错误及访问iis元数据库失败问题原因及解决办法
- JBPM deploy processdefinition 报错的问题原因及解决办法
- 有关跨域问题的原因 及 解决办法【转】
- 停止预览时调用Camera.release(), 出现Method called after release()异常问题原因及解决办法
- Oracle11g使用exp导出表不全问题的原因和解决办法
- Android 关于“NetworkOnMainThreadException”问题的原因分析及解决办法
- 关于Linux中文本出现^M问题的的原因分析和解决办法
- 对于js浮点数误差问题 完美解决办法
- js里面字符1和数字1相加的结果是11,如何解决这个问题。js里面使用EL表达式。
- 【转载】----web网站css,js更新后客户浏览器缓存问题,需要刷新才能正常展示的解决办法
- IE 下js里面new Date("2011-11-11") 出现nan的问题以及解决方法
- 解决node.js中使用for循环查询数据库异步执行的问题
- 解决error while loading shared libraries: xxx.so.x"类似问题办法和错误原因
- CentOS 7 安装问题:dracut_initqueue[599]: Warning: Could not boot 原因,及解决办法
- oracle使用exp导出dmp文件后表对象缺失问题的原因及解决办法