在 ES6 中的 React Class 上定义方法的两种方式有什么区别
What's difference between two ways of defining method on React Class in ES6
我在 ES6 React 代码中经常看到这种情况
class Foo extends React.Component {
bar = () => {
console.log("bar")
}
baz() {
console.log("baz")
}
}
似乎它们都在 Foo
上定义了方法 bar
和 baz
,但它们有何不同。
函数的编写方式和 this
、
的 context
的声明不同
在第一个语法中
bar = () => {
console.log("bar")
}
该函数是使用 Arrow function
语法编写的。
An arrow function does not have its own this
; the this
value of
the enclosing execution context
is used. Hence this
keyword inside
this function will refer to the context of the React class
然而第二个声明
baz() {
console.log("baz")
}
是一个简单的函数,这个函数中的this keyword
指的是函数本身的上下文。
所以当你尝试像 this.state
或 this.setState
那样访问 React class Properties/functions 时你会在第二种情况下得到一个错误(如果你没有使用绑定此函数的任何其他地方(示例构造函数)),而它在第一种情况下会起作用,因为对于箭头函数,this
在函数体内和在函数体外的意思相同。这意味着如果您在组件的自定义函数中使用箭头函数,它们可以毫无意外地使用 this
和 this.setState
。
在
上查看此答案
为简单起见,两者相等:
- bar = () => { ... }
- this.bar =this.bar.bind(这个)
前面的答案是绝对正确的,这就是为什么你想在 React classes 中使用箭头函数。
我还想指出一个细微的区别,即在 class 中使用它们的潜在陷阱以避免意外...
在 class 上定义的箭头函数 添加到实例中作为 属性 恰好是一个函数,而定义不是箭头函数将 将函数作为方法添加到 class 的原型。
在永远不会扩展的 React 组件中,这很好,但是如果出现这种情况,你想要子class 一个组件,你将无法覆盖期望能够调用的箭头函数基础 class 通过 super
,你只能完全覆盖它
class Button extends React.PureComponent {
// class method - overridable in subclass
pressMethod: function(): void {
console.log('beep')
}
// instance property functions - only overwriteable in subclass
pressArrow = (): void => {
console.log('boop')
}
pressArrowTwo = (): void => {
console.log('blip')
}
}
class BigRedButton extends Button {
// class method - overides subclass one,
// can call superclass method via `super`
pressMethod: function(): void {
super.pressMethod() // prints 'beep' to console
console.log('BOOOOOOOOM!!!')
}
// instance property function
// cannot call superclass via `super` as lambda's have no prototype
pressArrow = (): void => {
super.pressArrow() // TypeError - not a function
console.log('BOOOOOOOOM!!!')
}
// completely overwrites instance property of same name in subclass
// doesn't try to access prototype so won't error but is limited
pressArrowTwo = (): void => {
console.log('BOOOOOOOOM')
}
}
我在 ES6 React 代码中经常看到这种情况
class Foo extends React.Component {
bar = () => {
console.log("bar")
}
baz() {
console.log("baz")
}
}
似乎它们都在 Foo
上定义了方法 bar
和 baz
,但它们有何不同。
函数的编写方式和 this
、
context
的声明不同
在第一个语法中
bar = () => {
console.log("bar")
}
该函数是使用 Arrow function
语法编写的。
An arrow function does not have its own
this
; thethis
value of the enclosing executioncontext
is used. Hencethis
keyword inside this function will refer to the context of theReact class
然而第二个声明
baz() {
console.log("baz")
}
是一个简单的函数,这个函数中的this keyword
指的是函数本身的上下文。
所以当你尝试像 this.state
或 this.setState
那样访问 React class Properties/functions 时你会在第二种情况下得到一个错误(如果你没有使用绑定此函数的任何其他地方(示例构造函数)),而它在第一种情况下会起作用,因为对于箭头函数,this
在函数体内和在函数体外的意思相同。这意味着如果您在组件的自定义函数中使用箭头函数,它们可以毫无意外地使用 this
和 this.setState
。
在
为简单起见,两者相等:
- bar = () => { ... }
- this.bar =this.bar.bind(这个)
前面的答案是绝对正确的,这就是为什么你想在 React classes 中使用箭头函数。
我还想指出一个细微的区别,即在 class 中使用它们的潜在陷阱以避免意外...
在 class 上定义的箭头函数 添加到实例中作为 属性 恰好是一个函数,而定义不是箭头函数将 将函数作为方法添加到 class 的原型。
在永远不会扩展的 React 组件中,这很好,但是如果出现这种情况,你想要子class 一个组件,你将无法覆盖期望能够调用的箭头函数基础 class 通过 super
,你只能完全覆盖它
class Button extends React.PureComponent {
// class method - overridable in subclass
pressMethod: function(): void {
console.log('beep')
}
// instance property functions - only overwriteable in subclass
pressArrow = (): void => {
console.log('boop')
}
pressArrowTwo = (): void => {
console.log('blip')
}
}
class BigRedButton extends Button {
// class method - overides subclass one,
// can call superclass method via `super`
pressMethod: function(): void {
super.pressMethod() // prints 'beep' to console
console.log('BOOOOOOOOM!!!')
}
// instance property function
// cannot call superclass via `super` as lambda's have no prototype
pressArrow = (): void => {
super.pressArrow() // TypeError - not a function
console.log('BOOOOOOOOM!!!')
}
// completely overwrites instance property of same name in subclass
// doesn't try to access prototype so won't error but is limited
pressArrowTwo = (): void => {
console.log('BOOOOOOOOM')
}
}