js深刻(四)萬臉懵圈的this指向

做爲一個js菜雞的我而言,在以前講到過那麼多的js鏈式查找機制,好比說原型鏈,做用域鏈等等,想固然的把這個機制帶入到了this指向上邊,結果就是這個this指向指的我萬臉懵逼(標題換字了,擔憂被河蟹),在通過漫長的通(gou)俗(pi)易(bu)懂(tong)的 ECMAScript規範閱讀以後,分享一下我所認知的this指向node

簡而言之,js中this的指向不是在函數定義的時候肯定的,而是在調用的時候建立階段肯定的,也就是說this指向誰,徹底取決於函數的調用方式ecmascript

常見的幾種調用方式

  • 直接調用, 好比說函數

    function a() {
      console.log(this);  
      }
    
      a();

這個例子裏邊this指向的是全局對象,在客戶端的全局對象是window對象,在node 中的全局對象是global對象this

(function a() {
        function b() {
            console.log(this);  
        }
        b()
    })()

直接調用指的是直接用函數名稱後邊加()執行調用的函數,不管是否在全局做用域es5

  • 間接調用code

    const obj ={
          name:'obj對象',
          a(){
              console.log(this)
          }
      }
      obj.a()

如圖對象

在圖中咱們能夠看到咱們在對象裏邊調用對象裏邊的方法的時候,this指向的是obj對象,blog

或者說外邊有一個函數 而後給一個obj對象的屬性賦值ip

const obj ={
        name:'obj對象',
        a(){
            console.log(this)
        }
    }
    obj.a()
    obj.b=function(){
        console.log(this,'b')
    }
    obj.b()

打印的結果都是obj對象原型鏈

  • new調用

當咱們他用過new 建立一個新的對象的時候,new會調用這個構造函數來建立一個對象,那麼這個對象裏邊的this是這個被new的函數調用的,那麼天然 new調用的時候,this就是指向這個新對象的

function A(data) {
        this.data = data;
    }
    class B{
        constructor(data){
              this.data = data
        }
    }
    let a = new A("A");
    let b = new B("B");
    console.log(a.data);   
    console.log(b.data);

如圖

這個new,在建立對象的時候作了什麼,咱們會在下一篇博客裏邊仔細說明

  • 箭頭函數中的this

箭頭函數能夠理解成是是一個語法糖,他沒有本身的this綁定,箭頭函數中使用的this是包含他的那個函數的this

好比說

const obj = {
        a() {
            return () => {
                console.log(this);
            };
        }
    }

上邊這段代碼被轉譯成es5 的時候以下

const obj = {
    a: function a() {
        var _this = this;
        return function () {
            console.log(_this);
        };
    }
};

綜合以上全部的代碼,得出一個結論就是,在js中this的綁定正常來說是指向調用這個方法的對象來肯定的,固然還有一些不正常的方法,能夠改變this的指向

注意 ,下邊介紹的幾種方法,不能改變箭頭函數的this指向,箭頭函數自己是沒有this綁定的,在介紹完不正常的狀況後,再來講一說那些可以改變this指向的方法

ECMAScript 5.1 規範的this指向

js中this的綁定正常來說是指向調用這個方法的對象來肯定的

這句話在理論上是這麼講,在工做中正常的調用的話,這個理論是沒有毛病的,在 ECMAScript 5.1 的規範裏邊規定,在js裏邊分爲語言類型和規範類型

  • 語言類型

ECMAScript 裏邊的語言類型規定的是咱們能夠直接操做的一些類型,好比string number,object等等這些

  • 規範類型

規範類型ECMAScript 裏邊指的是一種抽象的規範,他們並非讓咱們用來進行操做的,二是用來描述一些行爲或者邏輯的,好比說typeof delete等等

ECMAScript 5.1 裏邊的this規定大概講就是這樣的,每一個對象裏邊有一個Reference 規範類型,this會根據Reference這個規範類型進行賦值

ECMAScript 5.1

規範奉上 Reference 這個東西你們簡單的理解成是()前邊的那一塊就行了,上邊咱們講的那些正常的就是說左邊是

  • 函數定義表達式
  • 屬性訪問表達式
  • 對象建立表達式
  • 屬性建立表達式

這幾種狀況,在這幾種狀況的時候上邊那句話是成立的

可是若是不是這上邊的那幾句話的時候,好比說括號裏邊是一個和函數相關計算或者一個運算符等等

這個時候this會指向undefined ,這個時候在非嚴格模式的狀況下會被隱式轉換成window對象

var value = 1;

    var obj = {
      value: 2,
      a() {
        return this.value;
      }
    }
    
    console.log(obj.a());
    console.log((obj.a)());
    console.log((obj.a = obj.a)());
    console.log((false || obj.a)());
    console.log((obj.a, obj.a)());

記得以前看到過這個一個例子,運行結果如圖

時間關係就說這些,下一篇博客會說new在運行時候過程和改變this指向的一些方法, 以上是我對this指向的一些認識,有不足的地方但願之處

相關文章
相關標籤/搜索