最近在被箭頭函數與普通函數的區別的時候,有一個很是重要的區別就是this指向問題。自己筆者比較笨的那種,因此下面我都理解,全網的程序員都應該沒問題。說重點。。。程序員
首先咱們來搞明白普通函數的this指向問題:windows
const obj = {
bg:function(){
console.log(this)
}
}
obj.bg() //obj
var dbl = obj.bg
dbj() //windows
複製代碼
上面代碼,obj對象裏面有一個bg的普通函數屬性,第一行執行obj.bg(),函數裏面的this指向obj這個對象。 第二行var dbl = obj.bg只作了賦值,並無執行,也就說如今dbl只是一個普通函數, 第三行執行dbl,此時普通函數裏面的this指向window。 因此上述總結:app
function test(){
console.log(this)
}
test() //windows
new test() //test對象
test.call({id:1}) // {id:1}對象
複製代碼
test是一個普通的構造函數,第一行執行此時普通函數裏面的this指向window,符合上述觀點,第二行new一個實例此時的this指向test的對象,這裏有些小夥伴比較蒙了,不是說好的誰調用指向誰嗎?怎麼回事,那是咱們不夠了解new到底作了什麼事。new關鍵字:1.建立了一個新的對象。2.將這個新的對象的__proto__指向了構造函數對象prototype對象。3.把構造函數的this指向這個新的對象而且執行,例如:test.call(newobj)。4.返回新的對象。這個樣一來咱們就明白執行實例化一個構造函數new test() 爲何指向test對象了。可是這不是我想表達的重點,咱們再看第三行test.call({id:1}),call方法你們都很熟吧,就是用來改變this指針的函數,而且執行這個構造函數(相應的還有bind、apply函數)。那麼這樣一來同一個構造函數,不一樣的調用方式,this指向的對象也是不同的。 因此上述總結:函數
再接着說剪頭函數,其實箭頭函數沒有this,必須經過查找做用域鏈查找決定值。ui
const obj = {
bg:() => {
console.log(this)
}
}
obj.bg() //windows
複製代碼
例子中的剪頭函數bg的在obj調用函數的時候,this對obj對象沒有綁定做用它會沿着做用域鏈往上找,再上層做用域是window因此輸出結果是window;也就是說箭頭函數沒有this,它的this取決於做用域鏈上的this。 在這裏筆者有一個誤區,就是總覺得bg的箭頭函數上一層做用域是obj這個對象的塊級做用域,其實bg是obj的一個屬性,他們應該是同一級的做用域,我來換種寫就可理解了const obj.bg = ()=> {}這樣上層做用域就是window( 這裏我仍是要很是感謝筆者的同窗X幫我從坑中解救出來,哈哈哈)this
function test1(){
return function(){
console.log(this)
}
}
var Test1 = new test1(); Test1() //windows
function test2(){
return ()=>{
console.log(this)
}
}
var Test2 = new test2(); Test2() //Test2
複製代碼
剪頭函數的特殊本質就是函數中的this沒有綁定做用,或者能夠這樣說:剪頭函數中的this其實始終指向的是函數定義時的this的指向而非執行時的。spa