在使用React时,是更倾向于在构造函数中使用箭头函数还是绑定函数?

10

在创建React类时,哪种方法更好?

export default class Foo extends React.Component {
  constructor (props) {
    super(props)
    this.doSomething = this.doSomething.bind(this)
  }

  doSomething () { ... }
}
或者
export default class Foo extends React.Component {
  doSomething = () => { ... }
}

我的一位同事认为后者会导致内存问题,因为Babel将代码转译为捕获闭包中的this,并且该引用将导致实例无法被GC清除。

你对此有什么想法吗?


Babel 对于 => 函数的处理方式与 .bind() 有何不同? - Pointy
使用箭头函数可以在闭包内保存this。 - davegri
是的。你认为 .bind() 是做什么的? - Pointy
我正在查看转译后的代码,它看起来并不完全相同,但我不太确定它在做什么。 - davegri
重点是,无论如何,“this”的上下文值都必须被保存在某个地方。在.bind()成为语言的一部分之前,它通常是通过闭包实现的,现在没有理由怀疑它基本上不是相同的(尽管有一些附加行为)。 - Pointy
可能是React.js ES6避免将'this'绑定到每个方法的重复问题。 - lux
3个回答

9
公共类字段语法(如doSomething = () => {...})尚未成为ECMAScript的一部分{{link1:但它表现良好,我相信它会实现}}。
因此,使用此语法会强制进行转译,但它带来以下优点:
  • 清晰、简洁的语法来表达this绑定
  • 对于浏览器支持此功能时具有未来的保障
  • 不需要考虑实现
对我来说,这是一个明显的胜利。在大多数情况下,您甚至不需要一个constructor(props),从而避免了那些样板式的super调用。
如果Babel实现会导致内存泄漏,那么肯定已经找到并快速修复了。相比之下,通过编写更多的代码,您更可能自己创建泄漏。

箭头函数是 ES2015 规范的一部分。 - Pointy
3
@Pointy 是的,但是公共类字段不是... - w00t

3
在渲染函数中绑定会导致在每次渲染时创建新的函数,这意味着diff算法认为有变化。而在构造函数中绑定则不会发生这种情况。
下面是使用箭头函数和在构造函数中绑定的编译差异: https://babeljs.io/repl/#?babili=false&evaluate=true&lineWrap=false&presets=es2015%2Creact%2Cstage-2&experimental=true&loose=false&spec=false&code=class%20x%20extends%20React.Component%20%7B%0A%20%20constructor%20(props)%20%7B%0A%20%20%20%20super(props)%3B%0A%20%20%20%20%0A%20%20%20%20this.onChange%20%3D%20this.onChange.bind(this)%3B%0A%20%20%7D%0A%20%20%0A%20%20onChange%20()%20%7B%20console.log(%27change%20x%27)%3B%20%7D%0A%7D%0A%0Aclass%20y%20extends%20React.Component%20%7B%0A%20%20onChange%20%3D%20()%20%3D%3E%20%7B%20console.log(%27change%20y%27)%3B%20%7D%0A%7D

我不是在问渲染中的绑定,而是在问使用箭头函数与在构造函数中绑定的区别。 - davegri
这是非常有价值的信息,我不明白为什么会被踩。 - João Vilaça
这是正确的答案。根据我的经验,使用箭头函数可能会导致内存泄漏,形式为分离的DOM节点。虽然看起来更好,但这里存在显着的内存成本。 - Hunt Burdick

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接