3

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

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

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

(我自己的猜测是 foo 在原型中,而 bar 在构造函数中?反正我不知道我在说什么)

4

4 回答 4

7

我自己的猜测是 foo 在原型中,而 bar 在构造函数中?

这是完全正确的。

foo() {}

在这种情况下是一个方法声明,并且值被分配给原型。相当于

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

bar = ... ;

另一方面是类字段。这是在构造函数中为实例分配属性的简写符号:

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

而且由于箭头函数的工作方式,使用带有箭头函数的类字段基本上可以让您创建“绑定”方法。

有关箭头函数的更多信息:箭头函数与函数声明/表达式:它们是否等效/可交换?


我什么时候应该使用哪个?

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

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

对于需要访问组件实例(例如调用或访问/ )的事件处理程序(即传递给其他函数/组件的函数)来说,情况大多如此。this.setStatethis.propsthis.state

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


正如另一个答案中所指出的,这与 React 完全无关。类字段很可能在今年正式集成到语言中。

于 2018-04-27T21:50:17.477 回答
1

在第二个例子bar中是一个箭头函数。

直到arrow函数,每个new 函数都定义了自己的this值。

例如,this在构造函数的情况下可以是一个新对象。

function Person(age){
  this.age=age;
  console.log(this);
}
let person=new Person(22);

或者如果创建的函数this可以像.baseobj.getAge()

let obj={
  getAge:function(){
    console.log(this);
    return 22;
  }
}
console.log(obj.getAge());

arrow函数不会创建自己的,this它只是使用执行的this值。另一方面,函数使用父作用域。enclosingcontextarrowthis

于 2018-04-27T21:49:11.783 回答
1

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} />
 }

}
于 2018-04-27T21:54:34.700 回答
0

本质上,没有区别。

不过,这与 React 无关。


箭头函数

箭头函数是添加到 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 类

在 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
    }
}
于 2018-04-27T21:58:04.060 回答