2017-04-25 56 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只会询问使用绑定的情况 –

相关问题