有时候我们会在不知不觉间创建出闭包,给我们打来不必要的麻烦。比如这一个经典的例子:
我们希望能把0-9这10个数字打印出来,但实际上每个函数都返回10.
对这一段代码的运行结果高程上是这么解释的:
“因为每个函数的作用域链都保存着其父函数(在这里就是Nico函数)的活动对象(每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中,在函数作用域中,也把变量对象称为活动对象),所以它们引用的都是同一个变量 i 。当父函数数返回后,变量 i 的值是10,此时每个函数引用的都是同一个变量对象,所以在每个函数内部 i 的值都是10.”
通俗点说就是:Nico函数的变量对象只有一个,所以for循环copy出来的10个子函数都只能引用同一个变量对象,而 i 值是被定义在变量对象中的,所以当 i 值更新为10之后,因为引用的同一个变量对象也相当于引用着同一个 i ,所以这10个函数最后都会返回10.
但是这样的解释实在有点过于理论了,所以我自己的理解是这样的:
“因为嵌套函数并没有被立即执行,所以循环10次之后只是保存10
个这样的函数 function(){ return i; },调用Nico函数把这10个
函数保存在数组中,在最后循环数组输出的时候再返回 i 值,但是
那时候for循环已经结束了,i 为10,所以执行结果便是弹出10个10;”
改写一下代码证明一下我的思路:
每循环一次我让匿名函数立即执行并返回一个对应的 i 值存在niconico变量当中,
这是执行结果
结果证明我的理解并没有错,我每一次循环都会立即把对应的 i 值返回出来,因为 i 是一直在变化的,如果等到循环结束才调用的话,到那个时候 i 的值已经是10了,照这种思路其实还可以这样写:我每一次循环并不立即执行返回相应 i 值,但是每一次循环我都把当时的 i 的值储存在对应的函数当中,等循环结束再调用的时候,每一个也都能返回正确的 i 的值。talk is cheap,show you the code:
上面代码执行结果也是一样的。
好的这就结束了,纰漏之处还请各路高手们不吝赐教。