3個閉包面試題解析

理解閉包造成的緣由,理解定義時和運行時的區別。面試

面試題1

var num = 1;
var o = {
    num: 2,
    add: function() {
        this.num = 3;
        console.log('add', this);
        (function() {
            console.log('closure', this);
            console.log(this.num);
            this.num = 4;
        })();
        console.log(this.num);
    },
    sub: function() {
        console.log(this.num);
    }
}
o.add();
console.log(o.num);
console.log(num);
var sub = o.sub;
sub();

// 請寫出輸出結果

zyx456的解釋:閉包

01,o.add();函數

第一個console.log('add', this);//輸出o這個對象。this

在對象方法中,方法中的this指向這個對象。spa

第一個this.num = 3;code

表示:o.num =3;對象

02,匿名自執行函數中的this,指向全局環境變量。爲window。blog

因此rem

(function() {

​            console.log('closure', this);//這裏的this是指向哪裏?window

​            console.log(this.num);//1

​            this.num = 4;//window.num = 4;

})();

匿名自執行函數的this.num爲window.num。爲1。it

this.num = 4;//window.num = 4;

03,

console.log(o.num);//3,由於前面修改了o.num=3;

04,console.log(num);//4

這裏,num爲window.num。

05,var sub = o.sub;

sub();//4

zyx456:sub爲函數。全局函數中的this指向全局環境,也就是window。

因此爲window.num爲4;


面試題2

function fun(n,o) {
  console.log(o)
  return {
    fun:function(m){
      return fun(m,n);
    }
  };
}
var a = fun(0);  
a.fun(1);  a.fun(2);  a.fun(3);//undefined,?,?,?
var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,?
var c = fun(0).fun(1);  c.fun(2);  c.fun(3);//undefined,?,?,?
//問:三行a,b,c的輸出分別是什麼?

zyx456分析:

var a =fun(0);

首先輸出console.log(o);//o未定義,爲undefined;

a =  {
   fun:function(m){
   return fun(m,0);
    }
}
a.fun(1);//返回 fun(1,0);=> console.log(0)=>0

a.fun(2);//返回fun(2,0);=>console.log(0)=>0

a.fun(3)//返回fun(3,0);=>console.log(0)=>0

因此:第一行輸出undefined,0,0,0

而後看第二行:var b = fun(0).fun(1).fun(2).fun(3);

fun(0)

首先輸出console.log(o);//o未定義,爲undefined;

等效於

{

   fun:function(m){
     return fun(m,0);

   }
}

fun(0).fun(1)

return fun(1,0)

fun(1,0)先輸出=>console.log(0)=>0

最後return結果爲

{
   fun:function(m){
       return fun(m,1);
    }
}

fun(0).fun(1).fun(2)

等同於

return fun(2,1)

fun(2,1)->輸出console.log(1);=>1

最後return結果爲

{
 fun:function(m){
       return fun(m,2);
       }
}

fun(0).fun(1).fun(2).fun(3)

等同於

return fun(3,2)

fun(2,1)->輸出console.log(2);=>2

最後return結果爲

{

 fun:function(m){
​        return fun(m,2);
​    }
}

因此:第一行輸出undefined,0,1,2

最後看第三行:var c = fun(0).fun(1); c.fun(2); c.fun(3);

var c=fun(0).fun(1);

同第二行的b。會輸出undefined和0,

c爲

{
    fun:function(m){
      return fun(m,1);
    }
}

c.fun(2)

return fun(2,1)=>輸出1。能夠看第二行b。

c.fun(3)

return fun(3,1)=>輸出1。能夠看第二行b。

因此:第一行輸出undefined,0,1,1

面試題3

// 最基礎題
for(var i = 1; i < 10; i ++){
    setTimeout(function(){
        console.log(i);
    }, 1000);
}

// 變體一
for (var i = 1; i < 10; i++) {
    (function(i){
        setTimeout(function(){
            console.log(i);
        }, i * 1000);
    })(i);
}

// 變體二
for (var i = 1; i < 10; i++) {
    (function(){
        setTimeout(function(){
            console.log(i);
        }, i * 1000);
    })();
}

// 變體三
for (var i = 1; i < 10; i++) {
    (function(){
        setTimeout(function(i){
            console.log(i);
        }, i * 1000);
    })();
}

zyx456:

最基礎:

1s後運行定時器,此時for循環已結束,i爲10。

變體1:

依次1秒輸出一個數字,閉包會使用for循環的值。

依次輸出1~9

變體2:

依次每隔1秒輸出10,10,10.。。。。

變體3:

在匿名自執行函數中,i未定義。因此輸出9個undefined。

相關文章
相關標籤/搜索