Babel 正在发挥它的魔力,这让我对发生的事情感到非常困惑。
这个 react 组件中的 foo 和 bar 有什么区别?我什么时候应该使用哪个?
class MyComponent extends Component {
foo() {
//...
}
bar = () => {
//...
}
}
(我自己的猜测是 foo 在原型中,而 bar 在构造函数中?反正我不知道我在说什么)
Babel 正在发挥它的魔力,这让我对发生的事情感到非常困惑。
这个 react 组件中的 foo 和 bar 有什么区别?我什么时候应该使用哪个?
class MyComponent extends Component {
foo() {
//...
}
bar = () => {
//...
}
}
(我自己的猜测是 foo 在原型中,而 bar 在构造函数中?反正我不知道我在说什么)
我自己的猜测是 foo 在原型中,而 bar 在构造函数中?
这是完全正确的。
foo() {}
在这种情况下是一个方法声明,并且值被分配给原型。相当于
MyComponent.prototype.foo = function() {};
bar = ... ;
另一方面是类字段。这是在构造函数中为实例分配属性的简写符号:
constructor() {
this.bar = ... ;
}
而且由于箭头函数的工作方式,使用带有箭头函数的类字段基本上可以让您创建“绑定”方法。
有关箭头函数的更多信息:箭头函数与函数声明/表达式:它们是否等效/可交换?
我什么时候应该使用哪个?
tl;dr 是:当您需要绑定函数时,使用类字段 + 箭头函数。
什么时候需要绑定函数?每当您希望this
在函数内部引用特定值但您无法控制函数的调用方式时。
对于需要访问组件实例(例如调用或访问/ )的事件处理程序(即传递给其他函数/组件的函数)来说,情况大多如此。this.setState
this.props
this.state
您不必使用它,您也可以在需要时绑定该方法。但是,在构造函数中只绑定一次方法对于 React 组件来说是理想的,因此,如果方法作为事件处理程序传递,则始终传递相同的函数对象。
正如另一个答案中所指出的,这与 React 完全无关。类字段很可能在今年正式集成到语言中。
在第二个例子bar
中是一个箭头函数。
直到arrow
函数,每个new
函数都定义了自己的this
值。
例如,this
在构造函数的情况下可以是一个新对象。
function Person(age){
this.age=age;
console.log(this);
}
let person=new Person(22);
或者,如果创建的函数this
可以像.base
obj.getAge()
let obj={
getAge:function(){
console.log(this);
return 22;
}
}
console.log(obj.getAge());
arrow
函数不会创建自己的,this
它只是使用执行的this
值。另一方面,函数使用父作用域。enclosing
context
arrow
this
foo
是类的实例方法MyComponent
。While是类bar
的实例属性MyComponent
(恰好被分配了一个匿名函数)。
看到它在传统意义上使用可能更有意义......
class MyComponent {
// instance property
someProperty = 42;
// instance method
someMethod() {}
}
那么为什么要使用实例属性而不是实例方法呢?
javascript中的实例方法必须在类范围内调用才能继承类上下文(this
)...
class MyComponent {
// instance method
someMethod() {
const value = this.state.value // ERROR: `this` is not defined
}
render() {
return <div onClick={this.someMethod} />
}
}
但是,由于箭头函数继承了它们的作用域,this
如果您使用箭头函数代替,则将可用
class MyComponent {
// instance method
someProperty = () => {
const value = this.state.value // this works!
}
render() {
return <div onClick={this.someProperty} />
}
}
本质上,没有区别。
不过,这与 React 无关。
箭头函数是添加到 Javascript 中的一项相对较新的功能,它为您提供了一种以更简洁的方式定义函数的方法。
function foo (param1, param2, etc) {
// do something
}
// becomes
var foo = (param1, param2, etc) => {
// do something
}
function foo (param) {
// do something
}
// becomes
var foo = param => {
// do something
}
{}
!function foo (param) {
returns param * 2
}
// becomes
var foo = param1 => param * 2
this
不是没有更新在箭头函数中,您不会得到新的this
- 它与父块中的相同。这在某些情况下可能很有用(setTimeout
例如,当使用 时)
在 ES6 中,我们还可以使用class
关键字在 Javascript 中定义“类”。不过,他们仍然使用原型!
function Something (foo) {
this.bar = foo;
}
Something.prototype.baz = function () {
return baz * 2
}
// becomes
class Something {
constructor(foo) {
this.bar = foo;
}
baz () {
return baz * 2
}
}
这样构造函数就完成了constructor()
,下面的所有方法都添加到了Prototype中。它只是语法糖(但有点为你做了一些原型繁重的工作)
extends
!class SomethingElse extends Something {
constructor(foo, lol) {
this.lol = lol
// Use super() to call the parent's constructor
super(foo)
}
baz () {
return baz * 2
}
}