2017-04-25 28 views
12

此問題與When using React Is it preferable to use fat arrow functions or bind functions in constructor?類似,但略有不同。您可以在構造函數中將函數綁定到this,或者只需在構造函數中應用箭頭函數。請注意,我只能在我的項目中使用ES6語法。我可以在反應組件的構造函數中使用箭頭函數嗎?

1.

class Test extends React.Component{ 
    constructor(props) { 
    super(props); 

    this.doSomeThing = this.doSomeThing.bind(this); 
    } 

    doSomething() {} 
} 

2.

class Test extends React.Component{ 
    constructor(props) { 
    super(props); 

    this.doSomeThing =() => {}; 
    } 
} 

什麼是這兩種方式的利弊?謝謝。

回答

7

由於某些原因,選項1通常更優選。

class Test extends React.Component{ 
    constructor(props) { 
    super(props); 

    this.doSomeThing = this.doSomeThing.bind(this); 
    } 

    doSomething() {} 
} 

原型方法更容易擴展。子類可以重寫或

doSomething() { 
    super.doSomething(); 
    ... 
} 

在實例屬性

this.doSomeThing =() => {}; 

或ES.next類字段

doSomeThing =() => {} 

被代替,調用super.doSomething()是不可能的擴展doSomething,因爲方法沒有在原型上定義。覆蓋它將導致在父項和子項構造函數中分配兩次this.doSomeThing屬性。

原型方法也到達了mixin的技術:

class Foo extends Bar {...} 
Foo.prototype.doSomething = Test.prototype.doSomething; 

原型方法更容易測試。它們可以窺探,存根或之前類實例化嘲笑:

spyOn(Foo.prototype, 'doSomething').and.callThrough(); 

這允許避免在某些情況下,競爭條件。

+0

感謝您的回覆!這個答案幫了我很多。你能否解釋更多關於'在某些情況下的競爭狀況'?謝謝。 – ycavatars

+0

例如,如果您想模擬doSomething或測試它被調用,但是在您有機會窺探/存儲實例之前調用它。如果在構造函數或代碼中的其他地方調用doSomething(當它是框架鉤子等)時,可能會發生這種情況。 – estus

+0

真的非常感謝您的解答。這有助於我找到潛在的錯誤,謝謝。 – ycavatars

3

我想你可能想要這樣。這與你的第一種情況是一樣的。 它將在階段2與巴貝爾一起工作。 (變換級屬性:http://babeljs.io/docs/plugins/transform-class-properties/) (預設階段2:http://babeljs.io/docs/plugins/preset-stage-2/

class Test extends React.Component{ 
 
    constructor(props) { 
 
    super(props); 
 
    } 
 
    doSomeThing =() => {} 
 
}

+0

這不是有效的es6。 –

+1

是的,但是使用bablerc,你可以在stage-2上使用插件,它可以工作。 (transform-class-properties:http://babeljs.io/docs/plugins/transform-class-properties/) (preset-stage-2:http://babeljs.io/docs/plugins/preset-stage- 2 /) – Wei

+0

我明白了,謝謝澄清。 –

1

檢查了這一點:

https://babeljs.io/repl/#?babili=false&evaluate=true&lineWrap=false&presets=es2015%2Creact%2Cstage-2&targets=&browsers=&builtIns=false&debug=false&code=class%20Dog%20%7B%0A%20%20constructor()%20%7B%0A%20%20%20%20%0A%20%20%20%20this.cat%20%3D%20_%3D%3E%20%7B%0A%20%20%20%20%20%20this%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D

我們可以看到巴貝爾transpiles

this.doSomeThing =() => { this }; 

分成

var _this = this; 
this.doSomething = function() { _this } 

編輯:我誤解了你的文章,但上述內容仍然真實有趣。 @CodinCat指出了一件重要的事情:在構造函數中聲明一個函數意味着在創建對象時需要時間(儘管很少),也可能需要內存,因爲該類的實例不共享相同的doSomeThing方法。

edit2:綁定(this)到函數實際上會導致上面列出的確切問題。換句話說,這兩種方法幾乎完全相同。

3

方法1對我來說更具可讀性,更具慣用性。

此外,在類中聲明方法而不是構造函數,方法可以共享。

class Foo { 
    constructor() { 
    this.test =() => {} 
    } 
} 

const f1 = new Foo() 
const f2 = new Foo() 
// the method is not shareable 
f1.test === f2.test // false 

理論上的方法2時速度較慢,但​​對性能的影響可以忽略不計:

class Foo { 
    test() {} 
} 

const f1 = new Foo() 
const f2 = new Foo() 
f1.test === f2.test // true 

在方法2,你會在您每次創建新實例時聲明的所有方法。

我只是去的方法1,因爲它在React documentation使用,我也從來沒有見過任何人因使用方法2.


我只是跑一些樣品來測試性能。在最新的Chrome(Mac)中,在構造函數中聲明方法比在構造函數中使用bind慢大約90%。

+2

當this.test = this.test.bind(this)'在像@ycavatars發佈的構造函數中時,您的第一個代碼示例不成立。f1.test = == f2.test將計算爲false –

+0

當然不是,'bind()'總是返回一個新的方法,但是方法本身的聲明可以被共享 – CodinCat

+0

但是@ycavatars只會詢問使用綁定的情況 –

相關問題