闭包和变量

来源:互联网 发布:java bug 工具 编辑:程序博客网 时间:2024/06/08 17:41

我之前经常遇到一个问题,为什么循环绑定函数只有最后一个函数如预期所想?或者说,为什么循环绑定函数,结果每一次绑定返回结果都一样?例如

function createFunction(){    var result=new Array();    for(i=0;i<10;i++){        result[i]=function(){            return i;        }    }    return result;}re=createFunction();re[5]();//10re[1]();//10

本来是希望他们返回的与他们自身的下标对应的,但是结果不过是多少,最后都返回10。
原因就是,第一,函数表达式是传址,也就是说每一个result[i]都是同一个指针,指向这个返回i的匿名函数。而等到要执行这个函数的时候也就是比如执行 re[5]()时,这个匿名函数才开始执行,此时执行就要获取i的值,就要去作用域中找,找到的i是外部函数的i的值,而因为外部函数已经执行完毕了,i的值已经是10了,所以都会返回10。
我更改一下函数,可能会更容易理解。

function createFunction(){    var result=new Array();    for(i=0;i<10;i++){        result[i]=function(){            return a;//访问一个全局变量的值        }    }    return result;}a=5;re=createFunction();//你可能以为已经执行完函数了,都会返回5a=6;//此时,我更改a的值re[5]();//6,结果它返回了6,说明实际上它是在你调用的时候才运行的,没用调用之前,它只是一个指针a=17;//再次更改re[5]();//17

这个理解了,上面那个函数也就可以理解,所以想给一个数组对象绑定一系列类似的且关于下标i的事件时,不能像上面那样子绑定,可以像下面这样子绑定

function createFunction(){    var arr=new Array();    for(i=0;i<10;i++){        arr[i]=function(num){            return function(){                return num;            }        }(i)//把i值传进去,那么num也就确定下来了,所以就不会受到外部函数i的干扰,这里把i写成num只是为了让读者更好的理解,其实写成i也是一样的,因为已经不是同一个i了。    }    return arr;}re=createFunction();re[5]();//5re[1]();//1

如果想更深入的了解这个问题,应该去看闭包和作用域的内容

原创粉丝点击