箭頭函數(shù):我只是this的搬運工

箭頭函數(shù)與傳統(tǒng)JavaScript的不同

先來談?wù)凟S5中的this

在ES5中,每個函數(shù)在被調(diào)用時都會自動取得this這個特殊的對象。因此,每個內(nèi)部函數(shù)不能訪問到外部函數(shù)的this對象。(跟變量訪問一樣,如果局部環(huán)境存在某個變量,就不會去搜索全局環(huán)境的同名變量)。

** this對象是在運行時基于函數(shù)的執(zhí)行環(huán)境決定的。**

執(zhí)行環(huán)境:

a.全局環(huán)境

運行在全局上下文(在任何函數(shù)體外部),this指向全局對象,并且,無論是否是在嚴(yán)格模式下,this都指代全局對象。在瀏覽器中,this指向window對象。

console.log(this === window);  // true;

b.函數(shù)環(huán)境

在函數(shù)內(nèi)部,this的值取決于函數(shù)是如何調(diào)用的。

  • 直接調(diào)用,非嚴(yán)格模式下,this默認(rèn)指向全局對象。不管調(diào)用的函數(shù)是在全局函數(shù)還是局部環(huán)境。

    function app() {
      console.log(this === window); // true
    }
    app(); // 全局調(diào)用
    function foo() {
        function bar() {
            console.log(this === window); // true
        }
        bar(); // 局部調(diào)用
    }
    foo();
    
  • 直接調(diào)用,嚴(yán)格模式下,this默認(rèn)指向undefined。不管調(diào)用的函數(shù)是在全局函數(shù)還是局部環(huán)境。

      'use strict'
    function app() {
      console.log(this === undefined); // true
    }
    app();
    function foo() {
        function bar() {
          console.log(this === undefined); // true
      }
      bar();
    }    
    foo();
    
  • 作為對象調(diào)用
    當(dāng)函數(shù)以對象的方法被調(diào)用時,它的this是調(diào)用該函數(shù)的對象,并且是距離最近的對象。

    var o = {
      sayName: function() {
      console.log(this === o); // true
      }
    }
    o.sayName();
    
  • 作為構(gòu)造函數(shù)調(diào)用

    當(dāng)函數(shù)被當(dāng)做構(gòu)造函數(shù)調(diào)用時,this指向剛要被創(chuàng)建的新對象。

    function Person() {
      this.name = 'noshower'; 
    }
    var person = new Person();
    console.log(person.name); //'noshower'
    
  • 使用call和apply調(diào)用,改變函數(shù)內(nèi)部this的綁定值。

     function foo() {
        console.log(this.name); //'noshower'
    }
    var obj = {
      name: 'noshower'
    }
    foo.call(obj); 
    

    // 函數(shù)foo內(nèi)部的this對象被綁定到了obj對象上。

  • 使用bind方法,會永久把this與一個對象綁定。無論這個函數(shù)如何被調(diào)用,都改變不了this

    function foo() {
      console.log(this.name); // 'noshower'
    }
    var obj1 = {
        name: 'noshower'
    }
    var obj2 = {
        name: 'DaLin'
    }
    var a = foo.bind(obj1); //用bind方法,將this進(jìn)行永久綁定。
    a.call(obj2); // 此時使用call方法將改變不了this的指向。
    

下面我們開始講ES6箭頭函數(shù)中的this對象

箭頭函數(shù)被調(diào)用的時候,不會自動綁定一個this對象。換句話說,箭頭函數(shù)根本就沒有自己的this。它的this都是捕獲自其所在上下文的this值。

  • 作為匿名函數(shù)被調(diào)用。

    function foo() {
      console.log(this);  //{name:'noshower'}
      setTimeout(() => {
          console.log('name:', this.name); //noshower
        }, 100);
    }
    var name = 'DaLin';
    foo.call({ name: 'noshower' });
    

上面代碼中,我們用call()方法,將函數(shù)foo的this對象綁定到了對象{name:'noshower'}上。由于,箭頭函數(shù)沒有this變量,所以,箭頭函數(shù)能夠訪問到外部環(huán)境的this變量。此時,箭頭函數(shù)內(nèi)部,訪問到的是foo函數(shù)的this對象。因此,this.name的值是'noshower'。

  • 作為方法被調(diào)用

      var obj = {
        name: 'noshower',
        sayName: () => this.name
    }
    var name = 'bar';
    console.log(obj.sayName());
    

上面代碼中,箭頭函數(shù)是作為對象的方法。因為,箭頭函數(shù)本身是不綁定this對象的。因此,它只能從外部搬運this對象。上面代碼中,只有全局環(huán)境存在this對象,因此返回的是window.name,即'bar'。

  • 在方法內(nèi)部被調(diào)用

    var obj = {
      name: 'noshower',
      sayName: function() {
          var a = () => this.name;
          console.log(a()); // noshower
      }
    }
    var name = 'bar';
    obj.sayName();
    

上面代碼中,箭頭函數(shù)是在sayName方法中運行的。此時,箭頭函數(shù)的this對象,搬運的是sayName方法的this對象。當(dāng)sayName函數(shù)作為方法調(diào)用時,它的this對象指向obj對象。因此,箭頭函數(shù)的this.name就是obj.name,即'noshower';

  • 使用new 操作符調(diào)用,會拋出錯誤

    var Obj = (name) => {
        this.name = name;
    }
    new Obj('noshower');
    

上面的代碼,箭頭函數(shù)作為構(gòu)造函數(shù)被調(diào)用,會報錯。原因是,箭頭函數(shù)沒有自己的this對象,就沒法給this添加屬性。

  • 使用call和apply,bind()調(diào)用

     var o = (val) => {
       console.log(this.name, val); // bar,bar
     };
      var obj = {
         name: 'foo'
     }
     var name = 'bar';
     o.call(obj, name);
    

上面代碼中,箭頭函數(shù)使用了call方法來調(diào)用。原本想將函數(shù)的this綁定在obj對象上面。結(jié)果顯示,this被綁定在了全局對象上了。這是因為,箭頭函數(shù)沒有自己的this對象,此時使用call方法僅僅起到了傳遞參數(shù)的作用,沒有改變它的this對象。它的this對象依舊來自外部執(zhí)行環(huán)境。

總結(jié)一下

箭頭函數(shù)沒有自己的this對象,它總是搬運外部環(huán)境的this對象。因此,只要離它最近的外部環(huán)境中的this改變,箭頭函數(shù)中的this就改變。如果離它最近的環(huán)境中的this,沒有改變。那么箭頭函數(shù)中的this就不會改變。

我不生產(chǎn)this,我只是this的搬運工。

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

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

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