ES6的class本質和react中須要使用bind(this)的緣由

ES6的class

咱們知道ES6新出一個規範是使用class關鍵字來定義一個類,這在之前是沒有的
在之前,須要在javascript裏實現面向對象,就須要使用prototypejavascript

什麼是面向對象?

面向對象有以下幾個基本特徵,一般認爲,只要實現了這幾個特性,就認爲是實現了面向對象:
1.封裝
2.繼承
3.多態
這裏不對三個基本特徵的作詳細展開。只須要知道,javascript實現繼承和多態都須要用到prototype
而ES6的class,本質上仍是ES5的prototype的語法糖java

什麼是語法糖?

語法糖就是提供了一種全新的方式書寫代碼,可是其實現原理與以前的寫法相同。
語法糖能夠說是普遍存在於各類計算機代碼中,包括C語言中的a[i]其實就是*a+i的語法糖。而今天對於咱們來講,a[i]其實已經很廣泛和經常使用了,因此也沒有人提這是語法糖這回事了。由於終極來講,全部語言都是彙編語言的語法糖:)react

class foo{
    constructor(){
    }
    a(){}
    b(){}
}

// 等價於
function foo(){};
foo.prototype = {
    constructor(){},
    a(){},
    b(){},
}

ES6的class跟ES5的定義方式用幾個不一樣

1.沒有變量提高
2.this指向不一樣函數

先來看1:this

test(); // 輸出'test'
function test(){
    console.log('test');
}

咱們知道即使在定義test函數以前執行test(),也是會獲得結果的。這是由於解析javascript代碼的時候會把全部的function test(){}這類代碼(即正常定義函數)都提高到最上方去定義。spa

可是這麼執行不行:prototype

let a = new test(); // 報錯
class test(){}

再看2:code

class Animal {
    printName () {
      this.print('Hello animal');
    }
    print(name) {
      console.log(name);
    }
}
const animal = new Animal();
animal.printName(); // 輸出'Hello animal'
const { printName } = animal;
printName(); // 報錯: Cannot read property 'print' of undefined

若是執行了bind對象

class Animal {
    constructor(){
        this.printName = this.printName.bind(this);
    }
    printName () {
      this.print('Hello animal');
    }
    print(name) {
      console.log(name);
    }
}
const animal = new Animal();
animal.printName(); // 輸出'Hello animal'
const { printName } = animal;
printName(); // 輸出'Hello animal'

發生了什麼?

animal中的printName函數的this本來指向的是執行環境,若是不執行bind,那麼printName函數的this指向window。
在執行new Animal()的時候,若是執行了bind,那麼從animal中獲取的printName函數,其this對象已經被綁定到了constructor的this,即animal上。
如下是this的指向
clipboard.pngblog

那麼咱們爲何須要在react裏bind(this)呢?

簡單來講,就是react在調用render方法的時候,會先把render裏的方法賦值給一個變量(好比變量foo),而後再執行foo()。
具體來講,以典型的綁定點擊事件爲例

<div onClick={this.clickHandler}></div>

react構建虛擬DOM的時候,會把this.clickHandler先賦值給一個變量。咱們假設是變量clickFunc = this.clickHandler;
而後,把虛擬DOM渲染成真實DOM的時候,會把onClick屬性值替換成onclick,並給onclick賦值clickFunc

在複雜的狀況中,可能存在屢次傳遞,若是不進行bind,那麼this的指向是必定會丟失的。

爲何react不本身集成bind到生命週期裏?

1是,沒有特別合適集成bind的地方2是,並非全部的函數都須要bind3是,隨意集成bind可能致使效率低下

相關文章
相關標籤/搜索