this魔術(shù)背后的秘密

作為一個(gè)前端學(xué)習(xí)者,在學(xué)習(xí)之路上總會(huì)遇到一些難題,突發(fā)奇想,便隨手記錄一下。

關(guān)于this

this作為javascript常用的關(guān)鍵字之一,被人們稱(chēng)為最復(fù)雜的機(jī)制之一,他就像一個(gè)魔術(shù)師,變幻著令人著迷的戲法,來(lái)混淆你的視聽(tīng)。而作為觀眾的我們?cè)谛蕾p完這眼花繚亂的魔術(shù)之后,總想了解一下背后的秘密。

理解this的指向

在js中,函數(shù)的幾種調(diào)用方式有:
普通函數(shù)調(diào)用
作為對(duì)象方法來(lái)調(diào)用
作為構(gòu)造函數(shù)來(lái)調(diào)用
使用apply/call方法來(lái)調(diào)用

this是在運(yùn)行時(shí)進(jìn)行綁定的,它的上下文取決于函數(shù)調(diào)用時(shí)的各種條件,this的綁定和函數(shù)聲明的位置沒(méi)有任何關(guān)系,只取決于函數(shù)的調(diào)用方式。
簡(jiǎn)單來(lái)說(shuō):this的最終指向的是那個(gè)調(diào)用它的對(duì)象(誰(shuí)調(diào)用這個(gè)函數(shù)或者方法,this就指向誰(shuí))

普通函數(shù)調(diào)用

  function foo(){
    this.x = 1;
    console.log(this.x);
    console.log(this);
  }
  foo(); // 1   window

在這段代碼中foo是直接使用了不帶任何修飾的函數(shù)引用進(jìn)行調(diào)用的,所以使用了默認(rèn)綁定,即作為全局對(duì)象window的方法來(lái)進(jìn)行調(diào)用的,可以看作window.foo();所以這里是window對(duì)象調(diào)用了foo這個(gè)方法,也就是說(shuō)foo函數(shù)當(dāng)中的this是指向window,同時(shí)window還具有了一個(gè)屬性x,值為1。

var x = 1;
  function foo(){
    console.log(this.x);
  }
  foo(); // 1

這里為了證明this是全局變量,進(jìn)行了一下小改變。一開(kāi)始定義的全局變量x作為window的屬性,在調(diào)用時(shí),this肯定是指向全局對(duì)象window。

但是在嚴(yán)格模式下,則不能將全局對(duì)象用于默認(rèn)綁定,因此this會(huì)綁定到undefined。

function foo(){
        "use strict";
    console.log(this.x);
  }
       var x = 1;
  foo(); // Uncaught TypeError: Cannot read property 'x' of undefined

雖然this的綁定規(guī)則完全取決于調(diào)用位置,但是只有foo()運(yùn)行在非嚴(yán)格模式下時(shí),默認(rèn)綁定才能綁定到全局對(duì)象。

作為對(duì)象方法的調(diào)用

var obj = {
            x : "1",
            foo: function() {
              console.log(this.x);
            }
       };
  obj.foo(); // 1

這里的this指向的是對(duì)象obj,因?yàn)槟阏{(diào)用這個(gè)foo是通過(guò)obj.foo()執(zhí)行的,那this就指向就是對(duì)象obj。再次強(qiáng)調(diào),this的綁定和函數(shù)聲明的位置沒(méi)有任何關(guān)系,只取決于函數(shù)的調(diào)用方式,誰(shuí)調(diào)用的就指向誰(shuí),這個(gè)很重要。

作為構(gòu)造函數(shù)來(lái)調(diào)用

function foo(){
      this.x = 1;
    }
    var obj = new foo();
    console.log(obj.x); // 1

這里可以實(shí)現(xiàn)輸出1是因?yàn)閚ew關(guān)鍵字可以改變this的指向,將this指向了obj對(duì)象。在傳統(tǒng)的面向類(lèi)語(yǔ)言中的new與js的new機(jī)制有著很多不同。在js中,構(gòu)造函數(shù)只是使用new操作符時(shí)被調(diào)用的函數(shù),不屬于某個(gè)類(lèi),也不會(huì)實(shí)例化一個(gè)類(lèi),只是被new操作符調(diào)用的普通函數(shù)。new是可以影響函數(shù)調(diào)用時(shí)this綁定行為的方法,稱(chēng)之為new綁定。

使用apply/call方法來(lái)調(diào)用

function foo(){
      console.log(obj.x);
 }
  var obj = {
    x:2
  };
  foo.call(obj); // 2

通過(guò)foo.call(),調(diào)用foo時(shí)將this綁定在了obj上。從this綁定的角度上,call()和apply()是一樣的。如果你把null或者undefined作為this綁定的對(duì)象傳入call,apply或者bind,在調(diào)用時(shí)會(huì)被忽略,執(zhí)行的是默認(rèn)綁定規(guī)則。

最后

如果要判斷一個(gè)運(yùn)行中的函數(shù)的this指向,就需要找到這個(gè)函數(shù)直接調(diào)用的位置。即誰(shuí)調(diào)用這個(gè)函數(shù)或者方法,this就指向誰(shuí)。

this雖然只是js里的一小部分,對(duì)于我們學(xué)習(xí)者而言還是很重要的。this還有很多奧秘等著我們?nèi)グl(fā)掘,我也只是知曉了其冰山一角,希望能分享一點(diǎn)自己的想法給一起學(xué)習(xí)路上的同學(xué)們,與君共勉。

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容