面试总结三

面试总结三

一道闭包经典面试题:

这道题很经典,对于理解闭包很到位,并且还可以稳固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

能看懂前面的代码执行解释,理解上面的代码执行输出就不会有问题了。

介意自己用笔纸在上面具体写出每次调用 n 的具体值为多少。连续运用了闭包的知识!

面试  基础  js