咱們知道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(){}, }
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的指向
blog
簡單來講,就是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的指向是必定會丟失的。
1是,沒有特別合適集成bind的地方2是,並非全部的函數都須要bind3是,隨意集成bind可能致使效率低下