class中的arrow function

前言

得益於class properties proposal,React的代碼變得簡潔了許多。在React中處理this綁定的時候,也習慣性地使用屬性聲明來替代過去constructor賦值的方式git

class A extends React.Component {
    constructor(props) {
        super(props);
        this.handleClick = this.handleClick.bind(this);
    }
    handleClick() {
        // do something
    }
}

// arrow function
class B extends React.Component {
    handleClick = () => {
       	// do something
    }
}
複製代碼

箭頭函數在聲明屬性的時候自動綁定 this,省去了在constructor中的函數覆蓋操做。es6

可是使用arrow function真的就一本萬利了嗎?github

class中的arrow function

// code 1
class Base {
    commonHandler = () => {
        // do something
        console.log('Base commonHandler', this.text);
    }
    text = 'base'
	selfHandler() {
    	console.log('selfHandler')
	}
}

class A extends Base {
    text = 'A'
	commonHandler(){
    	console.log('A commonHandler', this.text);
    }
}
const a = new A();
a.commonHandler(); // Base commonHandler A
複製代碼

上述代碼最終的執行會有點讓人意外,爲何text屬性發生了覆蓋,而commonHandler的函數卻仍是執行父類?babel

咱們經過babel編譯來先來看下這段代碼在es2017下的結果函數

class Base {
    constructor() {
        // commonHandler被移到了constructor中
        this.commonHandler = () => {
            // do something
            console.log('excute commonHandler', this.text);
        };

        this.text = 'base';
    }
    selfHandler() {
        console.log('selfHandler');
    }
}
複製代碼

能夠看到text屬性和箭頭函數commonHandler全被移到constuctor中,而正常成員方法selfHandler則沒有改變。es6的class中能夠經過相似寄生組合式繼承進行模擬,編譯結果fetch

class A執行繼承的後在constructor中將會調用父類的構造函數,而成員方法commonHandler掛載到了A的prototype上,實例化後按照方法查找的順序,先獲取的是實例上的方法。能夠經過將code 1中的a.commonHandler()替換爲a.__proto__.commonHandler()輸出了預期覆蓋父類方法的的結果'A commonHandler A'。優化

補充:class中的super在做爲對象使用時,在普通方法中指向的是父的原型對象,因此若是父類的方法是經過arrow function定義fn,則該方法在子類中將沒法經過相似super.fn()進行調用ui

濫用arrow function的影響

那咱們是否是能夠在子類中也經過arrow function對commonHandler進行綁定以達到覆蓋的目的?this

就結果而言的確這樣作,能夠根據上述對arrow function的分析,每指定一個arrow function都將會在contructor中出現,也就意味着多個地方實例化,將會建立多個方法,而不是像一般定義在原型上面,這樣定義的方法在全部的實例上共享。lua

那是否是意味着咱們要拋棄使用arrow function,答案是否認,咱們這裏要杜絕的是濫用,僅僅作有必要綁定的。好比onClick={this.doSomething}fetch.then(this.hanldeDone)

附上一個優化方案:autobind-decorator核心思路是僅在必要時綁定做用域

參考: Arrow Functions in Class Properties Might Not Be As Great As We Think

相關文章
相關標籤/搜索