`

JS中for循环里面的闭包问题的原因及解决办法

 
阅读更多

我们先看一个正常的for循环,普通函数里面有一个for循环,for循环结束后最终返回结果数组

复制代码
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],所以匿名函数的圆括号是可以去掉的。

以上就是几种解决for循环中闭包的办法,当然还有更多办法,大家可自行google或者bing其他资料来加深印象(百度是基本上搜不到什么有用的文章的)。

分享到:
评论

相关推荐

    浅谈JavaScript for循环 闭包_.docx

    浅谈JavaScript for循环 闭包_.docx

    浅谈JavaScript for循环 闭包

    下面小编就为大家带来一篇浅谈JavaScript for循环 闭包。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    浅谈js for循环输出i为同一值的问题

    1、最近开发中遇到一个问题,为什么每次输出都是5,而不是点击每个p,就alert出对应的1,2,3,4,5。 代码如下: &lt;html&gt; &lt;head&gt; &lt;meta http-equiv="Content-Type" content="text/html; charset=utf...

    JS中批量给元素绑定事件过程中的相关问题使用闭包解决

    在JS中,你写一个for循环的时候,内部的循环变量I其实是会保存在它运行的函数或类内的,所以你会发现你给元素批量绑定事件的时候,出现i=最后一个循环变量的值,这就很坑爹啊,解决的方案有2钟, 思路就是:把这个...

    javascript循环变量注册dom事件 之强大的闭包

    } 结果出现了问题,所有的dom都被注册了 i=n 的时候的事件,查了一些资料,说是在循环过程过this被改变,注册过的事件也被随之改变,找到了一种解决方法; 代码如下: for (var i=0; i&lt;n; i++) { (function (i){...

    js闭包引起的事件注册问题介绍

    背景:闲暇时间看了几篇关于js作用域链与闭包的文章,偶然又看到了之前遇到的一个问题,就是在for循环中为dom节点注册事件驱动,具体见下面代码: &lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;title&gt;js...

    JavaScript在for循环中绑定事件解决事件参数不同的情况

    有时候要对响应一堆相似的事件,但是每个事件的参数都不同,一开始还以为挺简单的,用个for循环不就得了,结果...}时,JavaScript引擎会先将for循环里的代码执行完, 当用户出发onclick事件时,JavaScript会寻找i,结

    深入理解ES6中let和闭包

    显然这段代码输出10,并没有向我们期望的返回3,原因也很简单(js的变量提升)函数在调用时候访问的是一个全局作用域的i,此时for循环已经执行完毕,全局变量i=10; 在ES5标准中,我们要想返回期望的3,通常的做法也...

    javascript闭包传参和事件的循环绑定示例探讨

    今天看到一个javascript的题目,按常理循环绑定事件,但是得到的结果却不是想要的。 代码如下: &lt;a&gt;text&lt;/a&gt; &lt;a&gt;link&lt;/a&gt; [removed] var as = document.getElementsByTagName(‘a’); for ( var i = as.length; ...

    JS 循环li添加点击事件 (闭包的应用)

    废话不多说了,直接给大家贴代码了,具体代码如下所述: ...以上所述是小编给大家介绍的JS 循环li添加点击事件 (闭包的应用),希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的。

    js代码-一个for循环例子带出来的问题. 常见面试题,涉及到同步异步执行,闭包,变量作用域等问题。

    js代码-一个for循环例子带出来的问题. 常见面试题,涉及到同步异步执行,闭包,变量作用域等问题。

    分析js闭包引起的事件注册问题

    背景:闲暇时间看了几篇关于js作用域链与闭包的文章,偶然又看到了之前遇到的一个问题,就是在for循环中为dom节点注册事件驱动,具体见下面代码: &lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;title&gt;...

    Javascript闭包演示代码小结

    闭包演示 p {background:gold;} function init() { var pAry = document.getElementsByTagName(“p”); for( var i=0; i ... 原因是初学者并未理解JavaScript的闭包特性。通过element.onclick=f

    JavaScript详解(第2版)

     6.3.3 for循环   6.3.4 for/in循环   6.3.5 使用break和continue控制循环   6.3.6 嵌套循环及标签   6.4 应知应会   练习   第7章 函数   7.1 什么是函数   7.1.1 函数声明和调用   ...

    js常见经典面试题汇总

    3.js中布尔值为false的六种情况 4.let const var 区别 5.普通函数和箭头函数的区别 6.数组有哪些方法 7.map()对比forEach() 8.for in 对比 for of区别 9.扁平化数组代码实现 10.数组去重的方法 11.防抖和...

    深入理解Javascript中的作用域链和闭包

    请先看上一篇中提到的for循环代码: var array = []; array.length = 10000000;//(一千万) for(var i=0,length=array.length;i&lt;length;i++){ array[i] = 'hi'; } var t1 = +new Date(); for(var i=0,length=...

    Node.js MongoDB AngularJSWeb开发中文版.part1

    2.4.3 for循环 17 2.4.4 for/in循环 18 2.4.5 中断循环 19 2.5 创建函数 19 2.5.1 定义函数 20 2.5.2 传递变量给函数 20 2.5.3 从函数返回值 20 2.5.4 使用匿名函数 21 2.6 理解变量作用域 22 2.7 使用JavaScript...

    JavaScript中的私有/静态属性介绍

    第6行可以访问到for循环块中的变量i,如果我们稍微修改以上代码,把for循环块放置在闭包中,情况就不一样了: 代码如下: (function () { (function () { for (var i = 0; i &lt; 10; i++) { //Do Nothing } })

Global site tag (gtag.js) - Google Analytics