Javascript 如何使用箭头函数(公共类字段)作为类方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31362292/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use arrow functions (public class fields) as class methods?
提问by Ben
I'm new to using ES6 classes with React, previously I've been binding my methods to the current object (show in first example), but does ES6 allow me to permanently bind a class function to a class instance with arrows? (Useful when passing as a callback function.) I get errors when I try to use them as you can with CoffeeScript:
我是在 React 中使用 ES6 类的新手,之前我一直将我的方法绑定到当前对象(在第一个示例中显示),但是 ES6 是否允许我使用箭头将类函数永久绑定到类实例?(在作为回调函数传递时很有用。)当我尝试像 CoffeeScript 一样使用它们时出现错误:
class SomeClass extends React.Component {
// Instead of this
constructor(){
this.handleInputChange = this.handleInputChange.bind(this)
}
// Can I somehow do this? Am i just getting the syntax wrong?
handleInputChange (val) => {
console.log('selectionMade: ', val);
}
So that if I were to pass SomeClass.handleInputChange
to, for instance setTimeout
, it would be scoped to the class instance, and not the window
object.
因此,如果我要传递SomeClass.handleInputChange
给,例如setTimeout
,它将作用域到类实例,而不是window
对象。
回答by Guy
Your syntax is slightly off, just missing an equals sign after the property name.
您的语法略有偏差,只是在属性名称后缺少等号。
class SomeClass extends React.Component {
handleInputChange = (val) => {
console.log('selectionMade: ', val);
}
}
This is an experimental feature. You will need to enable experimental features in Babel to get this to compile. Hereis a demo with experimental enabled.
这是一个实验性功能。你需要在 Babel 中启用实验性功能才能编译它。这是一个启用了实验性的演示。
To use experimental features in babel you can install the relevant plugin from here. For this specific feature, you need the transform-class-properties
plugin:
要在 babel 中使用实验性功能,您可以从这里安装相关插件。对于此特定功能,您需要transform-class-properties
插件:
{
"plugins": [
"transform-class-properties"
]
}
You can read more about the proposal for Class Fields and Static Properties here
您可以在此处阅读有关类字段和静态属性提案的更多信息
回答by Bergi
No, if you want to create bound, instance-specific methods you will have to do that in the constructor. However, you can use arrow functions for that, instead of using .bind
on a prototype method:
不,如果要创建绑定的、特定于实例的方法,则必须在构造函数中执行此操作。但是,您可以为此使用箭头函数,而不是.bind
在原型方法上使用:
class SomeClass extends React.Component {
constructor() {
super();
this.handleInputChange = (val) => {
console.log('selectionMade: ', val, this);
};
…
}
}
There is an proposalwhich might allow you to omit the constructor()
and directly put the assignment in the class scope with the same functionality, but I wouldn't recommend to use that as it's highly experimental.
有一个建议可能允许您省略constructor()
并直接将分配放在具有相同功能的类范围中,但我不建议使用它,因为它是高度实验性的。
Alternatively, you can always use .bind
, which allows you to declare the method on the prototype and then bind it to the instance in the constructor. This approach has greater flexibility as it allows modifying the method from the outside of your class.
或者,您始终可以使用.bind
,它允许您在原型上声明方法,然后将其绑定到构造函数中的实例。这种方法具有更大的灵活性,因为它允许从类的外部修改方法。
class SomeClass extends React.Component {
constructor() {
super();
this.handleInputChange = this.handleInputChange.bind(this);
…
}
handleInputChange(val) {
console.log('selectionMade: ', val, this);
}
}
回答by kennasoft
I know this question has been sufficiently answered, but I just have a small contribution to make (for those who don't want to use the experimental feature). Because of the problem of having to bind multiple function binds in the constructor and making it look messy, I came up with a utility method that once bound and called in the constructor, does all the necessary method bindings for you automatically.
我知道这个问题已经得到了充分的回答,但我只是想做出一点贡献(对于那些不想使用实验性功能的人)。由于必须在构造函数中绑定多个函数绑定并使其看起来很混乱的问题,我想出了一个实用方法,一旦在构造函数中绑定和调用,就会自动为您完成所有必要的方法绑定。
Assume I have this class with the constructor:
假设我有这个带有构造函数的类:
//src/components/PetEditor.jsx
import React from 'react';
class PetEditor extends React.Component {
constructor(props){
super(props);
this.state = props.currentPet || {tags:[], photoUrls: []};
this.tagInput = null;
this.htmlNode = null;
this.removeTag = this.removeTag.bind(this);
this.handleChange = this.handleChange.bind(this);
this.modifyState = this.modifyState.bind(this);
this.handleKeyUp = this.handleKeyUp.bind(this);
this.addTag = this.addTag.bind(this);
this.removeTag = this.removeTag.bind(this);
this.savePet = this.savePet.bind(this);
this.addPhotoInput = this.addPhotoInput.bind(this);
this.handleSelect = this.handleSelect.bind(this);
}
// ... actual method declarations omitted
}
It looks messy, doesn't it? Now I created this utility method
看起来很乱是不是?现在我创建了这个实用方法
//src/utils/index.js
/**
* NB: to use this method, you need to bind it to the object instance calling it
*/
export function bindMethodsToSelf(objClass, otherMethodsToIgnore=[]){
const self = this;
Object.getOwnPropertyNames(objClass.prototype)
.forEach(method => {
//skip constructor, render and any overrides of lifecycle methods
if(method.startsWith('component')
|| method==='constructor'
|| method==='render') return;
//any other methods you don't want bound to self
if(otherMethodsToIgnore.indexOf(method)>-1) return;
//bind all other methods to class instance
self[method] = self[method].bind(self);
});
}
All I now need to do is import that utility, and add a call to my constructor, and I don't need to bind each new method in the constructor anymore. New constructor now looks clean, like this:
我现在需要做的就是导入该实用程序,并添加对构造函数的调用,并且我不再需要在构造函数中绑定每个新方法。新的构造函数现在看起来很干净,像这样:
//src/components/PetEditor.jsx
import React from 'react';
import { bindMethodsToSelf } from '../utils';
class PetEditor extends React.Component {
constructor(props){
super(props);
this.state = props.currentPet || {tags:[], photoUrls: []};
this.tagInput = null;
this.htmlNode = null;
bindMethodsToSelf.bind(this)(PetEditor);
}
// ...
}
回答by Hemadri Dasari
You are using arrow function and also binding it in constructor. So you no need to do binding when you use arrow functions
您正在使用箭头函数并将其绑定在构造函数中。所以当你使用箭头函数时你不需要做绑定
class SomeClass extends React.Component {
handleInputChange = (val) => {
console.log('selectionMade: ', val);
}
}
OR you need to bind a function only in constructor when you use normal function like below
或者,当您使用像下面这样的普通函数时,您只需要在构造函数中绑定一个函数
class SomeClass extends React.Component {
constructor(props){
super(props);
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(val){
console.log('selectionMade: ', val);
}
}
Also binding a function directly in render is not recommended. It should always be in constructor
也不推荐直接在渲染中绑定函数。它应该总是在构造函数中