javascript - 绑定(bind) vs 箭头函数(在 JavaScript 中,或用于响应 onClick)

标签 javascript reactjs arrow-functions

所以我正在尝试学习 JavaScript 和/或 react 并且对理解 .bind(this) 有点困惑构造函数。不过,我现在想明白了,只是想知道,
为什么有人会在 JavaScript 中使用绑定(bind)而不是箭头函数?
(或在 onClick 事件中)。

使用一个与另一个相比有什么优缺点吗?

请参阅下面的代码示例。

绑定(bind)方法确保 clickEvent 函数中的 this 引用类:

class Click extends react.Component {
  constructor(props) {
    super(props)
    this.clickEvent = this.clickEvent.bind(this);
  }

  render = () => (
    <button onClick= { this.clickEvent } > Click Me < /button>
  )

  clickEvent() { console.log(this) } // 'this' refers to the class
}

但是下面的方法也引用了这个类:

class Click extends react.Component {

  render = () => (
    <button onClick= {() => { this.clickEvent() }}> Click Me < /button>
  )

  clickEvent() { console.log(this) } // 'this' refers to the class
}

最佳答案

首先,让我们从每种技术的例子开始吧!
但差异更多地与 JavaScript 语言本身有关。

绑定(bind):

import React from 'react';

class MyComponent extends React.Component {
  constructor(props) {
    super(props)
    this.clickHandler = this.clickHandler.bind(this);
  }

  clickHandler() {
    console.log( this )
  }

  render() {
    return <button onClick={this.clickHandler}>Click Me</button>
  }
}

箭头函数:

import React from 'react';

class MyComponent extends React.Component {
  constructor(props) {
    super(props)
  }

  clickHandler = () => {
    console.log( this )
  }

  render() {
    return <button onClick={this.clickHandler}>Click Me</button>
  }
}

优缺点:

在 public-class-field 上使用 Arrow-function 更易读, 因为更少的代码行, 但请记住,使用箭头函数会影响两件事:

首先是内存和性能;当您使用类字段定义函数时,您的整个方法驻留在类的每个实例而不是原型(prototype)上,但使用绑定(bind)技术,只是一个小callback 存储在每个实例上,它调用存储在原型(prototype)上的方法。

第二个可能受到影响的是您编写单元测试的方式。 您将无法使用组件原型(prototype)来 stub 函数调用,如下所示:

const spy = jest.spyOn(MyComponent.prototype, 'clickHandler');
// ...
expect(spy).toHaveBeenCalled();

必须找到另一种方法来 stub 该方法,例如,props 中传递虚拟回调,或者检查 状态改变

结论

计算机真的很擅长阅读代码;你不应该为此担心。 您可能需要考虑使用类属性箭头函数使您的代码更易于阅读。


其他工具:

如果您想同时保持人类可读性和性能,请考虑使用 plugin-transform-arrow-functions插件(尽管 v7.2.0 caused problems 对我来说),只需运行 npm i --save-dev @babel/plugin-transform-arrow-functions 并将其添加到您的“babel.config.js”或“.babelrc”文件,例如:

{
  "presets": ["module:metro-react-native-babel-preset"],
  "plugins": [
    ["@babel/plugin-proposal-decorators", { "decoratorsBeforeExport": false }],
    ["@babel/plugin-transform-arrow-functions", { "spec": true }]
  ]
}

或者你可以使用类似 auto-bind decorator 的东西,这会将上面的例子变成:

import React from 'react';

import { boundMethod as bind } from 'autobind-decorator';

class MyComponent extends React.Component {
  constructor(props) {
    super(props)
  }

  @bind
  clickHandler() {
    console.log( this )
  }

  render() {
    return <button onClick={this.clickHandler}>Click Me</button>
  }
}

Note that it's unnecessary to put @bind on every function. You only need to bind functions which you pass around. e.g. onClick={this.doSomething} Or fetch.then(this.handleDone)

关于javascript - 绑定(bind) vs 箭头函数(在 JavaScript 中,或用于响应 onClick),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50375440/

相关文章:

javascript - 在离开页面时进行 ajax 调用

javascript - 文本没有出现在 DOM 对象中?

javascript - 在不使用 () => function(someVal) 的情况下停止在挂载上执行的 onClick 函数

javascript - React - useCallback 与 useState 的 setState(prevState... 访问先前状态的区别

javascript - React Native 类方法中的 this

javascript - 从服务中获取硬编码的下拉值,而不是直接在 html 中显示

javascript - 在 css 中通过 Eslint 提交时出现错误

reactjs - 在 React 中向映射数组的特定项添加特定样式

javascript - jQuery map 中的箭头函数

javascript - 如何避免 Airbnb ESLint 中的 "Arrow function expect to return a value"错误