在 React 组件中,foo(){} 和 bar = () => {} 有什么区别,什么时候应该使用哪个?

In a React Component, what's the difference between foo(){} and bar = () => {} and when should I use which?

Babel 正在发挥它的魔力,这让我对发生的事情感到非常困惑。

这个react组件中的foo和bar有什么区别?我什么时候应该使用哪个?

class MyComponent extends Component {
  foo() {
    //...
  }
  bar = () => {
   //... 
  }
}

(我自己的猜测是foo在prototype里,bar在constructor里?反正我也不知道在说什么)

在第二个例子中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,它只是使用 enclosing 执行 contextthis 值。另一方面,arrow 函数使用父作用域的 this

My own guess is foo is in the prototype, and bar is in the constructor?

完全正确。

foo() {}

在此上下文中是一个 方法声明 并且值被分配给原型。相当于

MyComponent.prototype.foo = function() {};

bar = ... ;

另一方面是 class 字段。这是一个 shorthand 符号,用于在构造函数中为实例分配属性:

constructor() {
  this.bar = ... ;
}

并且由于箭头函数的工作原理,使用带有箭头函数的 class 字段基本上可以创建 "bound" 方法。

关于箭头函数的更多信息:


And when should I use which?

tl;dr 是:当您需要 bound 函数时,使用 class 字段 + 箭头函数。

什么时候需要绑定函数?每当您希望函数内部的 this 引用特定值但您无法控制 如何 调用函数时。

对于需要访问组件实例(例如调用 this.setState 或访问 this.props/this.state).

尽管您 不必 使用它,但您也可以在 需要时绑定方法。然而,在构造函数中只绑定一次方法对于 React 组件来说是理想的,这样,如果该方法作为事件处理程序传递,则始终传递相同的函数对象。


如另一个答案所述,这与 React 完全无关。 Class 字段可能会在今年正式集成到该语言中。

foo 是 class MyComponent 的实例 方法 bar 是 class MyComponent 的实例 属性(恰好被分配了一个匿名函数)。

在传统意义上使用它可能更有意义...

class MyComponent {

 // instance property
 someProperty = 42;

 // instance method
 someMethod() {}

}

那么为什么要使用实例 属性 而不是实例方法呢?

必须在 class 范围内调用 javascript 中的实例方法才能继承 class 上下文 (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 无关。


Arrow functions

箭头函数是添加到 Javascript 中的一项相对较新的功能,可让您以更简洁的方式定义函数。

function foo (param1, param2, etc) {
    // do something
}

// becomes

var foo = (param1, param2, etc) => {
    // do something
}

如果您只有 1 个参数,则不需要括号:

function foo (param) {
    // do something
}

// becomes

var foo = param => {
    // do something
}

如果只有1个表达式,返回结果,也可以省略{}

function foo (param) {
    returns param * 2
}

// becomes

var foo = param1 => param * 2

this不更新

在箭头函数中,您不会获得新的 this - 它与父块中的相同。这在某些情况下很有用(例如,使用 setTimeout 时)


JS Classes

在ES6中我们也可以使用class关键字来定义Javascript中的"classes"。 不过他们仍然使用原型!

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()中完成,并将以下所有方法添加到原型中。它只不过是语法糖(但有点为你做了一些原型繁重的工作)

您可以使用 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
    }
}