绑定与箭头函数(在 JavaScript 中,或用于响应 onClick) [英] Binding vs Arrow-function (in JavaScript, or for react onClick)

查看:28
本文介绍了绑定与箭头函数(在 JavaScript 中,或用于响应 onClick)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

两者之间有什么利弊吗?

请参阅下面的代码示例.

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

class Click extends react.Component {构造函数(道具){超级(道具)this.clickEvent = this.clickEvent.bind(this);}渲染 = () =>(<button onClick= { this.clickEvent } >点击我)clickEvent() { console.log(this) }//'this' 指的是类}

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

class Click extends react.Component {渲染 = () =>(<button onClick= {() =>{ this.clickEvent() }}>点击我)clickEvent() { console.log(this) }//'this' 指的是类}

解决方案

首先,让我们从每种技术的示例开始!
但区别更多的是与JavaScript 语言本身有关.

绑定:

从'react'导入React;class MyComponent 扩展了 React.Component {构造函数(道具){超级(道具)this.clickHandler = this.clickHandler.bind(this);}clickHandler() {控制台日志(这个)}使成为() {return <button onClick={this.clickHandler}>点击我</button>}}

箭头功能:

从'react'导入React;class MyComponent 扩展了 React.Component {构造函数(道具){超级(道具)}clickHandler = () =>{控制台日志(这个)}使成为() {return <button onClick={this.clickHandler}>点击我</button>}}

优点和缺点:

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

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

可能受到影响的第二件事是您如何编写单元测试.您将无法使用组件原型来存根如下所示的函数调用:

const spy = jest.spyOn(MyComponent.prototype, 'clickHandler');//...期望(间谍).toHaveBeenCalled();

必须找到另一种方法来存根方法,例如,通过props中传递间谍或检查state 变化.

结论

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


其他工具:

如果您想保持人类可读性和性能,请考虑使用 plugin-transform-arrow-functions 插件(虽然 v7.2.0 导致问题 对我而言),只需运行 npm i --save-dev @babel/plugin-transform-arrow-functions 并将其添加到您的babel.config.js"或.babelrc";文件,如:

<代码>{预设":[模块:metro-react-native-babel-preset"],插件":[[@babel/plugin-proposal-decorators", { decoratorsBeforeExport": false }],[@babel/plugin-transform-arrow-functions", {spec": true }]]}

或者你可以使用像自动绑定装饰器之类的东西,它会在上面例如:

从'react'导入React;import { boundMethod as bind } from 'autobind-decorator';class MyComponent 扩展了 React.Component {构造函数(道具){超级(道具)}@绑定clickHandler() {控制台日志(这个)}使成为() {return <button onClick={this.clickHandler}>点击我</button>}}

<块引用>

注意没有必要在每个函数上都加上@bind.你只需要绑定你传递的函数.例如onClick={this.doSomething}fetch.then(this.handleDone)

So I am trying to learn JavaScript and/or react and got a little mixed up with understanding .bind(this) in the constructor. However, I think to understand it now, and just want to know,
Why would anyone use Binding vs an Arrow-function in JavaScript?
(or in the onClick event).

Is there any pro/con to use one vs the other?

See below code samples.

Binding method ensures this in clickEvent function references the class:

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
}

However below method also references the class:

class Click extends react.Component {

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

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

解决方案

First of all, let's start with examples of each technique!
But the difference is more related to JavaScript language itself.

Binding:

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>
  }
}

Arrow-function:

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>
  }
}

Pros and Cons:

Using the Arrow-function on public-class-field is more human-readable, because of fewer lines of code, But keep in mind that using Arrow-function can affect two things:

First the memory and performance; When you use a class field to define a function, your whole method resides on each instance of the class and NOT on the prototype, but using the bind technic, just a small callback is stored on each instance, which calls your method that is stored on the prototype.

Second thing that can be affected is how you write your unit tests. You won't be able to use the component prototype to stub on function calls like below:

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

One would have to find another way to stub the method, for example, either by passing the spy in props or checking the state changes.

Conclusion

Computers are really good at reading code; you shouldn’t worry about that. You may want to consider making your code more human-readable by using a class-property arrow-function.


Other tools:

If you want to keep both human-readability and performance, consider using plugin-transform-arrow-functions plugin (although v7.2.0 caused problems for me), just run npm i --save-dev @babel/plugin-transform-arrow-functions and add it into your "babel.config.js" or ".babelrc" file, like:

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

Or you could use something like auto-bind decorator, which would turn above example into:

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 中,或用于响应 onClick)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆