function buildList(list){ var result=[]; for(var i=0;i<list.length;i++){ var item="item"+i; result.push(function(){ alert(item+" "+list[i]) }); } return result; //返回一个匿名函数数组 } function testList(){ var fnlist=buildList([0,1,2]); //返回一个有三个匿名函数元素的数组 for(var i=0; i<fnlist.length;i++){ //fnlist数组的长度为3, fnlist[i](); //我觉得此处应该是fnlist[0]():“item0 0”; fnlist[1]():“item1 1”; fnlist[2]():“item2 2”; } } testList(); //实际结果是"item2 undefined" 3 times
网上看到别人写的代码,可是不理解为什么最后弹出的结果是"item2 undefined" 3 times,我把自己的理解写在代码后面了。还请大神帮忙解释下这个代码块的执行情况
不是执行函数的问题.是定义函数时的问题
这种问题没啥意义.只要写js的时候明确知道变量的作用域就行
testList(); function buildList(list){ var result=[]; for(var i=0;i<list.length;i++){ var item=""; result.push(function(a){ item="item"+a; console.log(item+" "+list[a]); }); } return result; } function testList(){ var fnlist=buildList([0,1,2]); for(var i=0; i<fnlist.length;i++){ console.log(i); console.log(fnlist[i](i)); } }
这样改写是不是更好理解一些,你可以先打印下fnlist的值,都是同一个为闭包的值
我是过来逗比的..不过道理是这么个道理..首先,我们需要知道JS在解析的时候有一个预解析阶段,在这个阶段,函数,变量的声明会被提升,并不是全部提升到全局,而是提升到所在范围的最顶端.假设我们自己是JS解析器,来走一遍流程. 首先,预解析:有个叫buildList的函数,有个testList 的函数,还有个匿名的,然后就是各种变量提升.
然后调用testList 函数.第一句就是 fnlist=buildList([0,1,2]),好去找 buildList,buildList里有个循环,循环push一个函数,鬼知道是什么函数,反正函数没调用,直接原封不动的push,循环3次,i=3. 然后又来了一个循环,循环打印我刚才push的东西.此时应为我上回已经循环完了,所以我的i应该是3,但是list[3]?list是什么鬼,我不知道啊,(因为垃圾回收机制,buildList没有依赖,所以会被回收掉.),不知道就输出undefined,所以结果就是list2 undefined
所以这种问题就是写个闭包就行了,闭包就两个作用,一个就是读取变量,一个就是让变量常用内存.闭包写法 二楼的兄弟已经写好了,差不多就是这个道理.