这是一道经典的前端闭包的面试题,根据下面的函数,分别指出各打印的结果
function fun (n,o) {
console.log(o);
return {
fun: function (m) {
return fun (m,n)
}
}
}
let a = fun(0)
a.fun(1)
a.fun(2)
a.fun(3)
let b = fun(0).fun(1).fun(2).fun(3)
let c = fun(0).fun(1)
c.fun(2)
c.fun(3)
解:结果应该是:undefined,0,0,0
undefined,0,1,2
undefined,0,1,1
分析:
第一部分:最外面的fun有两个参数,但只给了一个实参,所以fun函数内:n=0,o=undefined,因而fun(0)打印undefined(不管传入多少都打印undefined)。
fun函数return一个对象,所以a指向这个对象:
{
fun:function(m){
return fun (m,n)
}
}。
a.fun(1)即为function(m){return fun (m,n)},且m=1,即a.fun(1)为fun(1,0)【0是之前传入的n】,由于在内部fun函数没有被定义,所以会沿着作用域链往外找,找到那个对象中的key值正好为fun,但是它没有两个参数,所以不匹配,继续往外找,一直找到最外面定义的fun函数,且有两个参数,找到了。所以a.fun(1)返回的就是最外面定义的那个函数,且根据形参的对应位置,把1赋给n,把0赋给o。所以a.fun(1)打印0。同样的原理,a.fun(2)即为fun(2,0),还是打印0,a.fun(3)同理。
第二部分:fun(0).fun(1)相当于之前的let a=fun(0), a.fun(1),即先后输出undefined、0,重点是接下来的部分:我们已经知道fun(0).fun(1)即为a.fun(1)也就是fun(1,0),是一个对象,则fun(0).fun(1).fun(2)就是对象中fun所对应的值,即function(m) {return fun(m,n)},此时m为2,同样的,n为之前传入的1,返回的函数同样会沿着作用域链向上找,最终fun(0).fun(1).fun(2)就是fun(2,1),从而打印1。接着,fun(2,1)返回的是一个对象,所以fun(0).fun(1).fun(2).fun(3)就是对象中fun所对应的值,即function(m) {return fun(m,n)},此时m为3,同样的,n为之前传入的2,fun(0).fun(1).fun(2).fun(3)也就是fun(3,2)打印2。
第三部分:undefined和0就不解释了,c就相当于第一部分中的a.fun(1)即fun(1,0),那么c.fun(2)就是第二部分中的fun(0).fun(1).fun(2),打印1,而c.fun(3)其实原理上是一样的,c是fun(1,0),返回一个对象,c.fun(3)就是function(m){return fun(m,n)},其中m=3,n=1,则c.fun(3)就是fun(3,1),打印1。
第一条博客,能力有限,如有错误,欢迎指正