面试总结三
一道闭包经典面试题:
这道题很经典,对于理解闭包很到位,并且还可以稳固js 的词法作用域。
function fun(n,o){
console.log(o);
return {
fun:function(m){ // [2]
return fun(m,n); // [1]
}
}
}
var a = fun(0);
a.fun(1);
a.fun(2);
a.fun(3);
var b = fun(0).fun(1).fun(2).fun(3);
var c = fun(0).fun(1);
c.fun(2);
c.fun(3);
以上代码等价与一下代码:
function _fun_(n,o){
console.log(o);
return {
fun:function(m){
return _fun_(m,n);
}
}
}
var a = _fun_(0);//undefined
a.fun(1); // 0
a.fun(2); // 0
a.fun(3); // 0
var b = _fun_(0).fun(1).fun(2).fun(3);
// undefined,0,1,2
var c = (0).fun(1); // undefined,0,
c.fun(2); // 1
c.fun(3); // 1
JS的词法作用域:
JS变量作用域存在于函数体中即函数体,并且变量的作用域是在函数定义声明的时候就是确定的,而非在函数运行时。
请看如下demo代码:
var name = "global";
function foo(){
// 先找自身体内的 name ; 没有发现再到外层找即为 全局环境发现了 name;
console.log(name);
}
function fooOuter1(){
var name="local";
foo();
}
fooOuter1();//输出global 而不是local,并且和闭包没有任何关系
function fooOuter2(){
var name="local";
function foo(){
console.log(name);
}
foo();
}
fooOuter2();//输出local 而不是global,在函数声明是name变量作用域就在其外层函数中,嗯嗯就是闭包~
执行输出结果分析:
var a = _fun_(0); // undefined
a.fun(1); // 0
a.fun(2); // 0
a.fun(3); // 0
此处的 fun 函数执行,因为第2个参数未定义,输出undefined,并且指向一个函数对象-带有闭包,能够访问到_fun_和变量n(此时 n 为 0) > 关于为什么未定义参数就输出 undefined 请参考 面试总结二:null 与 undefined 的区别。或者百度 / Google
a.fun(1) 执行返回的对象的fun方法,传入 m 的值 1,调用返回 fun(1,0),所以输出为 0;
同理: a.fun(2), a.fun(3) 和 a.fun(1) 一样输出为 0;
var b = _fun_(0).fun(1).fun(2).fun(3);
等价代码如下:
var b = _fun_(0); // undefined;
var b1=b.fun(1); // 0;
var b2=b1.fun(2);// 1; [3]
var b3=b2.fun(3);// 2; [4]
- 当[3]被调用时,b1对象中有一个闭包,引用了_fun_函数及外层函数变量n=1,所以匿名函数执行的函数调用为fun(2,1),输出结果为1,并返回一个新的对象。
- 当[4]执行时,b2对象也有一个闭包,引用了_fun_函数及外层函数变量n=2,执行fun(3,2),输出结果为2
var c = _fun_(0).fun(1);//undefined,0,
c.fun(2);//1
c.fun(3); //1
能看懂前面的代码执行解释,理解上面的代码执行输出就不会有问题了。