草庐IT

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

coder 2024-05-15 原文

所以我正在尝试学习 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 - 绑定(bind) vs 箭头函数(在 JavaScript 中,或用于响应 onClick)的更多相关文章

  1. ruby-on-rails - Railstutorial : db:populate vs. 工厂女孩 - 2

    在railstutorial中,作者为什么选择使用这个(代码list10.25):http://ruby.railstutorial.org/chapters/updating-showing-and-deleting-usersnamespace:dbdodesc"Filldatabasewithsampledata"task:populate=>:environmentdoRake::Task['db:reset'].invokeUser.create!(:name=>"ExampleUser",:email=>"example@railstutorial.org",:passwo

  2. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  3. ruby - ruby 中的 TOPLEVEL_BINDING 是什么? - 2

    它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput

  4. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  5. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  6. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  7. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  8. ruby-on-rails - 每次我尝试部署时,我都会得到 - (gcloud.preview.app.deploy) 错误响应 : [4] DEADLINE_EXCEEDED - 2

    我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie

  9. ruby - inverse_of 是否适用于 has_many? - 2

    当我使用has_one时,它​​工作得很好,但在has_many上却不行。在这里您可以看到object_id不同,因为它运行了另一个SQL来再次获取它。ruby-1.9.2-p290:001>e=Employee.create(name:'rafael',active:false)ruby-1.9.2-p290:002>b=Badge.create(number:1,employee:e)ruby-1.9.2-p290:003>a=Address.create(street:"123MarketSt",city:"SanDiego",employee:e)ruby-1.9.2-p290

  10. ruby - 在 Ruby 中按名称传递函数 - 2

    如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只

随机推荐