扫码关注官方订阅号
为什么f1(),f2(),f3(),都是16,而不是1,4,9?谢谢
光阴似箭催人老,日月如移越少年。
因为等主程序运行完(for循环结束时),再调用push里面函数,这个时候i=4,加个闭包即可
function count() { var arr = []; for (var i=1; i<=3; i++) { arr.push(function (i) { return function(){ return i*i }; }(i)); } return arr; }
arr中的匿名函数在运行的时候,内部的循环早到结束了,i那时候是4。
代码中闭包作用域中i值为循环结束时的值,即为4。所以调用f1 f2 f3 三个函数中保存的作用域中的i均为4,故三个函数调用的结果均为16;
arr[0],arr[1],arr[2]中存的都是匿名函数啊,所以当arr[0]()执行的时候再去找i,这时候i已经是 4了,所以是16啊
count()在结束时返回的是(function(),function(),function())三个函数。
count()
(function(),function(),function())
所以,results[0],results[1],results[2]均为函数,即f1(),f2(),f3()均为函数,返回i * i;
results[0],results[1],results[2]
f1(),f2(),f3()
而在循环结束的时候,由于i++,i的值已经变为4,所以f1(),f2(),f3()均返回i*i,即4*4=16。
i*i
4*4=16
for循环开始时就开始调用push里面的函数了,只不过指向i地址的值一直在变,最后i=4.导致数组里面指向i地址值也变为4了。
现有的回答没有一个真正答在点子上的。三个值都一样要用作用域来解释,i 的值都是 4 要用闭包来解释
真实的原因在于内部的三个匿名函数,看似都在访问各自独立的 i,但是问题就在于这个 i 是外层的(var 定义的变量具有函数级作用域而且会提升),三个匿名函数共享了外层 count 的作用域里的 i
count 函数只调用了一次,而三个内部匿名函数在真正调用是发生在 count 调用之后,但是三个函数又含有对 i 的引用所以形成了一个闭包,变量 i 得到了保护。i 的值是循环结束之后的 4,这时候三个内部函数又共享了这个作用域,所以引用到的 i 的值都是 4
所以要想让结果是 1,4,9,就要让内部函数的访问的 i 与外层 count 函数隔离,可以像现在的采纳回答里面的那样用一个 IIFE 把内部匿名函数包裹起来(但那个不叫“加个闭包”),i 的值用参数传进去
或者另外一种方法就是用 ES6 里的 let 来定义 i。ES6 对 for 循环里的初始条件用 let 定义的变量有特殊处理,会把每次循环都重新定义一次,并且值使用上次循环结束的值作为当前循环的初始值。这样的话就解除了内部匿名函数对外层作用域的共享
let
微信扫码关注PHP中文网服务号
QQ扫码加入技术交流群
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
PHP学习
技术支持
返回顶部
因为等主程序运行完(for循环结束时),再调用push里面函数,这个时候i=4,加个闭包即可
arr中的匿名函数在运行的时候,内部的循环早到结束了,i那时候是4。
代码中闭包作用域中i值为循环结束时的值,即为4。
所以调用f1 f2 f3 三个函数中保存的作用域中的i均为4,故三个函数调用的结果均为16;
arr[0],arr[1],arr[2]中存的都是匿名函数啊,所以当arr[0]()执行的时候再去找i,这时候i已经是 4了,所以是16啊
count()在结束时返回的是(function(),function(),function())三个函数。所以,
results[0],results[1],results[2]均为函数,即f1(),f2(),f3()均为函数,返回i * i;而在循环结束的时候,由于i++,i的值已经变为4,所以
f1(),f2(),f3()均返回i*i,即4*4=16。for循环开始时就开始调用push里面的函数了,只不过指向i地址的值一直在变,最后i=4.导致数组里面指向i地址值也变为4了。
现有的回答没有一个真正答在点子上的。三个值都一样要用作用域来解释,i 的值都是 4 要用闭包来解释
真实的原因在于内部的三个匿名函数,看似都在访问各自独立的 i,但是问题就在于这个 i 是外层的(var 定义的变量具有函数级作用域而且会提升),三个匿名函数共享了外层 count 的作用域里的 i
count 函数只调用了一次,而三个内部匿名函数在真正调用是发生在 count 调用之后,但是三个函数又含有对 i 的引用所以形成了一个闭包,变量 i 得到了保护。i 的值是循环结束之后的 4,这时候三个内部函数又共享了这个作用域,所以引用到的 i 的值都是 4
所以要想让结果是 1,4,9,就要让内部函数的访问的 i 与外层 count 函数隔离,可以像现在的采纳回答里面的那样用一个 IIFE 把内部匿名函数包裹起来(但那个不叫“加个闭包”),i 的值用参数传进去
或者另外一种方法就是用 ES6 里的
let来定义 i。ES6 对 for 循环里的初始条件用 let 定义的变量有特殊处理,会把每次循环都重新定义一次,并且值使用上次循环结束的值作为当前循环的初始值。这样的话就解除了内部匿名函数对外层作用域的共享