关于作用域和js执行机制的一道面试题

题目:

​
    var funcs = []
    for (var i = 0; i < 10; i++) {
        funcs.push(function() { return i; })
    }
    funcs.forEach(function(func) {
        console.log(func());
    })

这题输出多少呢?

答案:十个10。

为什么?

当然了,不排除已经会的童鞋了,如果会的话,请关闭这篇博文,不然只会浪费时间。如果不会,那么请务必好好看看。

回答之前,我们再看看这道题变化后输出是什么样子的:

        var funcs = [];
	    for (var i = 0; i < 10; i++) {
	        funcs.push(function() { return i; })
	        console.log(funcs[i]());
	    }

	    funcs.forEach(function(func) {
	        console.log(func());
	    })

那么这道题的打印的又是些什么值呢?

答案:0.1.2.3.4.5.6.7.8.9和十个10.

为什么呢?

其实大家把两段代码用浏览器即可验证出来了,细心的同学甚至就知道为什么了。

下面我把两段代码在浏览器中打印的值的图放出来:

 

1.首先,函数或者说方法只有在调用的是时候才会执行其内部语句,否则相当于只定义了一个方法,这里举个栗子:

 

这里我在里面定义了一个名为test的函数,但是里面的变量tested根本就未定义,但是在浏览器中是不会报错的,但只要我们调用了这个函数,那么浏览器会报错:

 

2. 知道之后,我们便可知原题中,由于funcs数组Push进去了十个匿名函数,但由于尚未调用,所以里面的i并未打印出来,但是实质上里面的i的确是0,1,2,3,4,5,6,7,8,9。但是在for循环外面在调用数组中的函数时,是因为在for循环体外,出了for循环的作用域,作用域这里我就不再解释了,所以导致后面在调用的时候,i的已经变成了for循环结束之后的值了,也就是10,也因此打印出十个10.

3.修改后的代码也就是第二段代码为什么打印的是0,1,2,3,4,5,6,7,8,9,是因为它在for循环体内,在作用域内,因此能访问到正确的i值。

好,分析完了,那么我们有什么方法可以修改原题之后,达到我们想要的效果,也就是分别打印出0,1,2,3,4,5,6,7,8,9呢?

博主这里提供两种:

1)ES5的方法:立即调用函数方法

    // ES5知识,我们可以利用“立即调用函数”解决这个问题
    var funcs = []
    for (var i = 0; i < 10; i++) {
        funcs.push(
          (function(value) {
            return function() {
                return value;
            }
        })(i)
      )
    }
    funcs.forEach(function(func) {
        console.log(func())
    })

2)ES6的方法:


    const funcs = [];
    for (let i = 0; i < 10; i++) {
        funcs.push(function() {
            console.log(i)
        })
    }
    funcs.forEach(func => func())

猜你喜欢

转载自blog.csdn.net/Charles_Tian/article/details/82147904
今日推荐