2017-06-15 54 views
0

我很難找到我的頭。 我知道範圍鏈接,javascript中的回調函數,其值爲這個中的回調函數和箭頭函數。javascript這個封閉的外部函數有一個綁定'this'

在JavaScript中,閉包可以通過作用域鏈訪問封閉函數的變量。那麼爲什麼閉包不能通過Function.prototype.bind訪問'this'的綁定函數?變量「this」不是範圍鏈的一部分嗎?

冉鉻控制檯中下面的代碼:

a = 4; 
b = 6; 
function outer(){ 
    function inner(){ 
     console.log(`this.a is ${this.a} and this.b is ${this.b}`); 
    } 
    inner(); 
} 
outer.bind({a:1,b:3})() 

和控制檯掀開:

this.a is 4 and this.b is 6 
+0

這是因爲你有全局變量! inner內部的'this'仍然是訪問全局變量的'window'。 – Li357

+0

@AndrewLi好吧,我明白了,不應該內部訪問外部的綁定a和b,因爲它是一個閉包? – basum

+0

不,因爲你在封閉中訪問'this'。它與外部功能無關。 – Li357

回答

0

是變量「這」不是一個範圍鏈的一部分?

是的,正好。 this不是一個變量,而是一個特殊的關鍵字。它確實設置爲,每調用函數,在你的情況下inner()outer範圍內的this是什麼都沒有關係。

雖然函數可以選擇退出此行爲,但有一個例外:箭頭函數。他們確實查this詞彙,而忽略從調用值:

function outer(){ 
    const inner =() => { 
     console.log(`this.a is ${this.a} and this.b is ${this.b}`); 
    } 
    inner(); 
} 
outer.call({a:1,b:3}) 
+0

所以解釋器在內部首先檢查函數調用是「方法」還是「正常函數調用」,在前一種情況下,這是該方法附加到的obj,而在後者中,即使是全局對象該函數是一個閉包,並不附加到全局對象[當然,在非嚴格模式]。 ? ? – basum

+0

是的,這就是它檢查的內容。請注意,它不會將全局對象傳遞給'inner()',它會傳遞'undefined' - 它不會像你說的那樣附加到任何東西上。這只是馬虎模式函數,它將這個參數未定義爲全局對象,就像箭頭函數或者邊界函數選擇忽略該值一樣。 (總是嘗試嚴格模式:D!) – Bergi

0

正如評論所說,這是一個contextual reference,它能夠基於你如何調用該函數(或定義它,如果我們認爲箭頭功能)。看看你的代碼的修改版本,顯示此上下文行爲:

var a = 4; 
var b = 6; 
function outer(){ 
    document.write(`<p>[outer] this.a is ${this.a} and this.b is ${this.b}</p>`); 

    function inner(msg){ 
     document.write(`<p>[${msg}] this.a is ${this.a} and this.b is ${this.b}</p>`); 
    } 
    inner('inner'); 
    this.inner = inner; 
    this.inner('this.inner'); 
} 
outer.bind({a:1,b:3})(); 

這將輸出:

[outer] this.a is 1 and this.b is 3 

[inner] this.a is 4 and this.b is 6 

[this.inner] this.a is 1 and this.b is 3 

工作演示here

1

這和封鎖是JS和2個不同的機制應不要混在一起。 這個在外部函數中與內部函數完全分離。

在你的例子中,你期望內部函數具有這個來自外部函數的詞法範圍,這不是這是如何工作的。如果你正在使用箭頭函數,它就是這樣工作的,因爲這樣做會是詞法,並且會從外部函數指向這個。 如果你改變內部函數箭頭功能你可以觀察到的行爲// this.a是1和this.b是3

常量內=()=> { 的console.log(this.a is ${this.a} and this.b is ${this.b}); };如果你想了解這是怎麼表現我非常凱爾 - 辛普森建議書,它是免費的在GitHub上this & object prototypes

從書

爲了理解這個綁定,我們必須理解call-site:調用函數的代碼中的位置(不是聲明它的地方)。我們必須檢查呼叫站點來回答這個問題:這是什麼這是一個參考?

所以就像你可以看到內部函數的位置與這將綁定到什麼無關。 rules that defines how this will be bound

閱讀上面的鏈接後,你應該對JS有更多的瞭解。