鍍金池/ 問答/人工智能  HTML/ js閉包題目求解

js閉包題目求解

var obj = {
    a:3,
    b:function(){
        console.log(this,1);
        var that = this;
        var s = function(){
            console.log(this,2);
            console.log(that,3);
        }
        return s;
    }
}
obj.b()();

來,求大神解釋一下,為什么第二個輸出是全局對象。this不應(yīng)該訪問的是父級內(nèi)的this么?


繼續(xù)再追問一下

var obj = {
    a:3,
    b:function(){
        console.log(this,1);
        var that = this;
        var s = function(){
            console.log(this,2);
            console.log(that,3);
        }
        s();
    }
}
obj.b();

這種情況下,2為什么也是window呢?

回答
編輯回答
孤客

this不是在定義對象的時候就確定了的,this的值取決于調(diào)用的對象,obj.b()首先返回了function s,然后執(zhí)行s(),這時候this已經(jīng)不是obj了。

2017年11月19日 22:44
編輯回答
真難過

代碼:

var obj = {
    a:3,
    b:function(){
        console.log(this,1); // 第一個this
        var that = this;     // that
        var s = function(){
            console.log(this,2); // 第二個this
            console.log(that,3); // that
        }
        return s;
    }
}
obj.b()();

調(diào)用 obj.b()() 等價于如下:

let b = obj.b(); 
b();

obj.b()執(zhí)行時:

第一個this綁定到 obj,是{a:3,b:function(){/* */}}
that被賦值第一個this,同樣也是{a:3,b:function(){/* */}}
第二個this,因為沒有被調(diào)用,所以保留。實際調(diào)用時再綁定。
所以這時,代碼變成了下面這樣:

let b = function() {
    console.log(this,2); // 第二個this
    console.log({a:3,b:function(){/*  */}},3); 
}
b();

b()執(zhí)行時:

第二個this綁定到全局對象

沒毛病吧,哈哈哈?

2018年5月11日 23:15
編輯回答
終相守

其實這里就是this的隱式丟失了。
一個隱式丟失的過程是這樣子的:

var obj = {
    a: function() {
        console.log(this);
    }
};
obj.a(); //作為對象的方法使用,隱式綁定,this為這個對象。
var b = obj.a
b(); //賦給一個變量,發(fā)生隱式丟失,this指向window。

可以這樣理解,this詞法是跟調(diào)用的方式有關(guān)的,當調(diào)用obj.a()的時候,這個函數(shù)是基于obj對象來調(diào)用的,它作為對象的方法來調(diào)用,所以很顯然this指向obj
var b = obj.a其實就等價于:

var b = function() {
    console.log(this);
}

于是當你調(diào)用b的時候,這是對b的直接調(diào)用,故指向window。
所以再看回你的代碼。
當你return了一個函數(shù)時,這里創(chuàng)建了一個閉包,that保存了對詞法作用域的引用。
這個時候,obj.b()就等價于

function s() {
    console.log(this,2);
    console.log(that,3);
}

又因為創(chuàng)建了閉包,所以that能夠訪問得到原來的詞法作用域。但是這里的this跟函數(shù)調(diào)用的方法有關(guān),它相當于直接調(diào)用了一個s函數(shù),所以this自然指向window。
你可以去看下《你不知道的JS(上卷)》,里面this一節(jié)講得十分清楚。


補充第二段代碼解釋:
其實這就是對函數(shù)的獨立調(diào)用,默認綁定到了window對象上面。
剛剛的說法有點小錯誤。
this詞法與函數(shù)調(diào)用的位置調(diào)用的方式有關(guān)。
一般情況下,都是先找到函數(shù)調(diào)用的位置,再判斷調(diào)用的方式。按照你的代碼,其實就是兩種方式。

  • 一種是默認綁定,就是對函數(shù)的獨立調(diào)用,指向window,嚴格模式下指向的是undefined。
  • 一種是隱式綁定,就是作為對象的方法去調(diào)用。但是這種情況很多時候會出現(xiàn)隱式丟失。

綜上,第一段代碼,就是隱式丟失的情況。第二段代碼,僅僅只是對于函數(shù)的獨立調(diào)用,雖然是在obj中的b被調(diào)用的,僅此而已。

2017年1月3日 15:28
編輯回答
硬扛

因為返回的是一個函數(shù),函數(shù)此時是沒調(diào)用的,等到下面調(diào)用的時候,這時的this是指向window的。

2018年8月23日 14:38
編輯回答
晚風(fēng)眠

我的理解是return 出去的時候其實 obj.b()就是這個S 而這個S,這時的調(diào)用對象是window window.s() ,所以第二個輸出了window。如有誤,還請指出

2018年7月5日 00:43
編輯回答
你的瞳
obj.b() ---> function(){
            console.log(this,2);
            console.log(that,3);
        }

obj.b()() ---> function(){
            console.log(this,2);
            console.log(that,3);
        }()
2018年8月31日 19:52