React中使用ES7语法定义实例属性的一些问题

仅代表个人的一点看法,欢迎探讨~

先看这样一段代码:

class App extends Component {
  constructor(props) {
    super(props)
    this.state = { name: 'Dell' }
    this.handleClick = this.handleClick.bind(this)
  }
  handleClick() {
    this.setState({
      name: 'Lee'
    })
  }
  render() {
    return (
      <div>
        <div onClick={this.handleClick}>
          {this.state.name}
        </div>
      </div>
    )
  }
}

这是ES6中比较常见的一个demo,里面考虑到了作用域绑定,也考虑到了未来子组件重新渲染的性能优化问题。

在ES7中,我们可以不借助constructor来直接定义实例属性了,于是,代码可以这么写,大家可以运行下,也是没问题的。通过箭头函数,可以解决掉作用域的问题,同时,也保存了箭头函数的引用,不会因为传给子组件的函数引用发生变化导致性能上的消耗,constructor也就可以省略掉了,代码变得简洁了不少。

class App extends Component {
    state = {
        name: 'dell'
    }
    handleClick = () => {
        this.setState({name: 'lee'})
    }
    render() {
        return (
            <div>
                <div onClick={this.handleClick}>{this.state.name}</div>
            </div>
        )
    }
}

可是,这样做会额外带来一些新的问题,其中最主要的一个问题在于当我们定义实例属性的时候,实例属性都会直接存储在对象上,而不是对象的原型上。也就是说,handleClick这样的实例方法,当你使用箭头函数定义时,每创建一个实例,就会多出一个,消耗内存。而且,在Node中,并没有实现对直接定义实例属性的支持,所以这段代码如果做服务器端渲染也是无法运行的。

另外借鉴留言区 @蒋正 的观点,这种方式,子类继承父类时,实例方法可以直接使用或者覆盖,但无法通过super的形式进行继承后的扩展,会限制复杂场景中的代码设计。

综上,最靠谱的方法还是老老实实使用最上面的代码吧~

Dell Lee:Es7中的实例属性zhuanlan.zhihu.com图标