我真的懂 this 嗎

先知

this 其實是在函數被調用時發生的綁定,它指向哪裏徹底取決於函數在哪裏被調用。面試

大提示: 不想看分析的能夠直接拉到最後看結論。

面試常見題

第一題

function foo(){
  console.log(this.a)
}
var obj = {
  a :2,
  foo:foo
}
var bar = obj.foo
obj.foo() 
bar()  
複製代碼

問: 最後兩個打印出什麼?數組

第二題

function foo(){
  console.log(this.a)
}
var obj = {
  a :2,
  foo:foo
}
var obj2 = {
  a:1,
  obj:obj
}
var obj3 = obj2.obj.foo
obj2.obj.foo() // 2
obj3() //undefined
複製代碼

問: 最後兩個打印出什麼? 答?bash

咱們如何理解 this 綁定的究竟是誰?或者說 this 究竟是誰?下面介紹四種方法

1. 默認綁定

什麼是默認綁定呢?上代碼先app

var a = 2;
function foo(){
  console.log(this.a)
}
function foo2(){
  'use strict'
  console.log(this.a)
}
foo() // 2
foo2() //  TypeError: Cannot read property 'a' of undefined
複製代碼
  • 在上面的代碼中,「 foo() 直接使用時不帶任何修飾的函數引用進行調用的 」, 所以只能使用「默認綁定」
  • 因此到 foo() 中的 this 綁定到「 全局對象 window 」,而「 嚴格模式 」時,全局對象沒法被綁定,因此 this 綁定到 「undefined」

默認綁定總結:默認綁定即不帶任何修飾的函數引用被調用時的綁定,此時 this 綁定到「 全局對象 window 」或者 「undefined」函數

2. 隱式綁定

隱式綁定是什麼呢?隱式的綁定

當函數引用有上下文對象時,隱式綁定會把函數調用中的 this 綁定到這個上下文對象。ui

那麼回到面試題this

2.1 面試題一

function foo(){ console.log(this.a)}
var obj = { a :2,  foo:foo }
var bar = obj.foo
obj.foo() //2
bar()  /undefined

複製代碼

foo() 被調用時,落腳點指向 obj 對象(上下文對象),因此 this 綁定到 obj ,this.a 即 obj.a , 因此打印出了 2spa

可是爲何 bar() 打印出了 undefined 呢?prototype

雖然 bar 是 obj.foo 的引用,但其實是 foo函數 自己的引用,因此此時 bar() 是不帶任何修飾的函數調用,使用默認調用code

2.2 面試題二

function foo(){ console.log(this.a)  }
var obj = {  a :2,  foo:foo  }
var obj2 = {  a:1,  obj:obj   }
var obj3 = obj2.obj.foo
obj2.obj.foo() // 2
obj3() //undefined
複製代碼

跟上面一題相同,雖然引用鏈比較長,可是最後 foo() 是在 obj 中被調用,因此 this 綁定到 obj ,引用鏈只有最後一層影響調用位置。

隱式綁定總結 : 函數在上下文對象中調用時, this 綁定到 上下文對象上。

3. 顯式綁定

使用「 call apply bind 」 進行綁定 this , this 綁定到第一個傳入的參數

MDN三者的用法

3.1 call 的使用

回到面試題第一題,咱們使用「 call 」進行顯式綁定

function foo(){ console.log(this.a)  }
var obj = {
  a :2,
  foo:foo
}
var bar =obj.foo
obj.foo() // 2
bar.call(obj) //2
複製代碼

此時二者都打印出 2 ,由於咱們將 this 綁定到 obj ,打印出的便是 //obj.a //2

3.2 apply 綁定第一個參數是 this , 二參是 一個數組

3.3 bind 是 綁定第一個參數是 this

顯式綁定總結: 使用call apply bind 時,第一個參數是 this ,不傳的話,默認爲 undefined 。

4. new 綁定

使用 new 來調用函數, 到底作了什麼 ?
    1. 建立一個全新的對象
    1. 這個新對象的__proto__ 連接到 構造函數的 prototype
    1. 這個新對象會綁定到函數調用的 this
    1. 若是函數沒有返回其餘對象,那麼 new 表達式中的函數調用會自動返回這個新對象。
function foo(a){
  this.a = a 
}
var bar = new foo(2)

console.log(bar.a) // 2
複製代碼

分析: 使用 new 調用 foo() 時,咱們構造一個對象並把它綁定到 foo() 調用的 this 上

####new 綁定總結: new 綁定中 this 綁定的就是新生成的對象

總結

    1. 「 箭頭函數 」內的 this 就是外面的 this ,外面的 this 是啥看下面四條
  • 2 . 「 new 綁定 」函數是否在 new 中調用 ? 若是是 this 綁定的便是 新建立的對象。 var bar = new foo()

    1. 「 顯式綁定 」函數是否經過 call 、apply、 bind 綁定?this綁定的時第一個參數 var bar = foo.call(obj)
  • 4.「 隱式綁定 」 函數是否在某個上下文中調用? 是的話,this 綁定的是那個上下文對象 var bar = obj.foo()

    1. 「 默認綁定」若是都不是,那麼就是默認綁定。嚴格模式綁定到 undefined ,不然綁定到 全局對象 var bar = foo()

後記

你要是看不懂我也沒辦法了,個人修爲都在這了。。。。

文章爲我的總結,不足之處還請留言或私信。

轉載請註明出處。

以上。

相關文章
相關標籤/搜索