问题 2:在循环中使用闭包
"闭包" 这个词会经常提到,因为别人能通过这个问题的回答判断你对预言的熟悉程度,以及考察你是否知道什么时候使用闭包。
什么是闭包?
它就是能访问作用域外部变量的内部函数。闭包能用来实现私有化和创建工厂函数等作用。关于闭包常见的题目是这样的:
写一个函数,循环一个整数数组,延迟 3 秒打印还这个数组中每个元素的索引。
这个问题常见(不正确)的实现是这样:
- const arr = [10, 12, 15, 21];
- for (var i = 0; i < arr.length; i++) {
- setTimeout(function() {
- console.log('The index of this number is:' + i);
- },
- 3000);
- }
但是如果你运行这段函数,你会发现 3 秒之后每次都打印的是 4,而不是预期的 0,1,2,3.
为了正确的找到出现这种情况的原因,你需要理解 Js 是如何运行这段代码的,这也是考察你的地方。
原因是 setTimeout 函数创建了一个访问外部作用域的函数(闭包),就是包含索引 i 的那个循环。3 秒之后,函数开始执行打印 i 的值,而此时循环也结束了,i 的值已经是 4. 因为循环遍历 0,1,2,3,4 后最终停在了 4.
实际上有好几种方法能正确解决这个问题。这里有两个:
- const arr = [10, 12, 15, 21];
- for (var i = 0; i < arr.length; i++) { // 给每个函数传入变量i,让其能访问正确的索引 setTimeout(function(i_local){ return function(){ console.log('The index of this number is:'+i_local); } }(i),3000); }
另一种:
- const arr = [10, 12, 15, 21];
- for (let i = 0; i < arr.length; i++) { // 使用ES6中let关键字,它会在函数调用时创建一个新的绑定 setTimeout(function(){ console.log('The index of this number is:'+i); }(i),3000); }
就爱阅读 www.92to.com 网友整理上传, 为您提供最全的知识大全, 期待您的分享,转载请注明出处。
来源: http://www.92to.com/bangong/2017/03-09/18354816.html