对于“输出十个10面试题”的理解
题目如下:
var funcs = [] for (var i = 0; i < 10; i++) { funcs.push(function() { console.log(i) }) } funcs.forEach(function(func) { func() })
第一眼看到的时候以为会输出0~9,结果输出的是十个10,果然入坑了。。(小白的无知)于是在网上查了一下,发现与匿名函数,闭包,作用域等问题相关,下面就说一下我的理解。
首先得知道什么是匿名函数,以及它什么时候才会执行,参考于 https://www.cnblogs.com/ranyonsue/p/10181035.html
这里的 function() { console.log(i) }) 就是一个匿名函数,它是不会自动执行的,除非给它加上括号,那么为什么会输出十个10呢?原因是后面的 func() 语句调用了这个函数。
对于for循环中执行的 funcs.push(function() { console.log(i) }) 实际上是funcs这个数组被push了10个匿名函数,其次,每个匿名函数在执行时都会打印已经被累加的变量i,而这个被打印出来的i值不是0~9,而是10,因为只有等for循环结束之后(此时i已经为10)才会去调用匿名函数。这里的 i 由于用var声明,所以是一个全局变量,最终循环结束, i 保存在内存中不会马上销毁,所以你在for循环结束的时候输出 i 可以看到结果为10。关于闭包问题请参考 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures
for循环结束后,调用数组的 forEach 方法对数组进行相关处理,关于forEach详细介绍请参考 https://www.runoob.com/jsref/jsref-foreach.html
forEach()可以传入一个匿名函数作为参数,而该匿名函数有含有三个参数,其依次代表数组遍历时的当前元素item,数组遍历时的当前元素的索引index,以及正在遍历的数组array。有了这三个参数,可以方便我们做很多事情。其中第一个参数(数组遍历时的当前元素item是必需的,其他两个可选)。
那么对于 function(func) { func() } 这里的 func 其实就是数组funcs里面的元素,也就是匿名函数,然后再 func()执行匿名函数,从而输出十个10。
var funcs = [] for (var i = 0; i < 10; i++) { funcs.push( (function(value) { return function() { console.log(value) } })(i) ) } funcs.forEach(function(func) { func() })
方法二:通过ES6来解决
const funcs = [] for (let i = 0; i < 10; i++) { funcs.push(function() { console.log(i) }) } funcs.forEach(func => func())
以上就是对本道题的理解。