使用ES的class,究竟是使用箭頭函數更有效率,仍是在構造器函數(constructor)中使用bind函數給函數綁定context更加有效率?在Demystifying Memory Usage using ES6 React Classes文章中,給出了以下的結論。react
上圖是在class中使用箭頭函數建立類的方法。做者稱其爲class properties. 能夠看得出,使用箭頭函數在類中定義的handler方法,在其的每個實例中都會有一個獨立的handler函數。當實例的數量很少的時候,這種方式不會帶來很大的內存浪費,但當實例成千上萬的時候,這種方式就會顯得在內存使用上效率很低。如果可以共享類上的handler豈不是更好。es6
而使用構造器函數綁定,則可以更加有效的減小內存的使用。經過在構造器函數裏面綁定函數,以下代碼:bash
class MyClass extends Component {
constructor() {
super();
this.state = { clicks: 0 };
this.handler = this.handler.bind(this);
}
handler() {
this.setState(({ clicks }) => ({ clicks: clicks + 1 }));
}
render() {
const { clicks } = this.state;
return(
<button onClick={this.handler}>
{`You've clicked me ${clicks} times`} </button> ); } } 複製代碼
每個實例裏面雖然都有handler方法(this.handler,不是MyClass.prototype.handler),但每一個實例中的this.handler實際上都共享MyClass.prototype.handler的函數體。app
那麼這是如何作到的呢? Bind函數MDN Polyfill實現:函數
if (!Function.prototype.bind) {
Function.prototype.bind = function(oThis) { //oThis 表明object this
if (typeof this !== 'function') {
// closest thing possible to the ECMAScript 5
// internal IsCallable function
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this, //
fNOP = function() {},
fBound = function() {
return fToBind.apply(this instanceof fNOP
? this
: oThis,
// 獲取調用時(fBound)的傳參.bind 返回的函數入參每每是這麼傳遞的
aArgs.concat(Array.prototype.slice.call(arguments)));
};
// 維護原型關係
if (this.prototype) {
// Function.prototype doesn't have a prototype property fNOP.prototype = this.prototype; } fBound.prototype = new fNOP(); return fBound; }; } 複製代碼
從上面的代碼能夠看出,咱們在構造器中使用bind綁定函數之後,實際上返回了一個函數(fBound),所返回的函數的函數體和待綁定(MyClass.prototype.handler)的函數體是不一樣的。所返回的函數只是在函數體內調用了待綁定的函數。換句話說,經過在構造器中使用bind綁定函數之後,所生成的實例中,都會有一個獨立的fBound,函數體相對於待綁定的函數較小,而每一個實例中的fBound在被調用時都會共享待綁定的函數(MyClass.prototype.handler)ui
經過對比能夠發現,使用構造器bind的方法,每一個實例均可以有效地共享函數體,從而更加有效的使用內存。但當要綁定的函數較多時,這種方法又顯得相對的枯燥和無聊。因此,我認爲在知道實例很少,函數體不大的前提下,使用箭頭函數更加快捷。this