重要的是要知道这个语法:
class A {
method = () => {}
}
只是在类构造函数中创建实例方法的语法糖:
class A {
constructor() {
this.method = () => {}
}
}
注意:这个语法目前还不是 JavaScript 语言的正式部分(
目前处于第三阶段),所以你必须使用
转译器,如 Babel 来处理它。
在
method
内部,
this
的值为类
A
,因为在构造函数中
this
指向它(由于
箭头函数 继承了它们定义所在作用域的上下文)。
class A {
constructor() {
this.method = () => this;
}
}
const instance = new A();
console.log(instance.method() === instance);
在类上定义一个常规(非箭头)函数方法会在类原型(而不是实例)上创建一个方法,但不会设置关于
this
会是什么(因为在JS中
this
是动态的
并取决于函数的调用方式,而不是定义方式)。
class A {
method() {}
}
console.log(new A().method === A.prototype.method);
如果以这两种方式定义的方法在类实例上被调用(通过
.
),根据当函数作为对象的方法被调用时如何绑定
this
的规则,
this
在两种情况下都将指向类实例:
class A {
constructor() {
this.methodOnInstance = () => this;
}
methodOnPrototype() { return this; }
}
const instance = new A();
console.log(
instance.methodOnInstance() === instance.methodOnPrototype(),
instance.methodOnPrototype() === instance
);
上述两种方法声明之间的一个主要区别是实例方法中的this
始终固定为类实例,而类(原型)方法不是(我们可以使用Function.prototype.apply或Function.prototype.call更改它)
class A {
constructor() {
this.methodOnInstance = () => this;
}
methodOnPrototype() { return this; }
}
const instance = new A();
console.log(
instance.methodOnInstance() === instance.methodOnPrototype(),
instance.methodOnPrototype.call('new this') === 'new this'
);
在事件处理程序中,常见的情况是this
发生变化。在这种情况下,事件处理程序调用传递给它的函数,并将上下文绑定到发生事件的元素上(因此覆盖了this
的值,使其成为被单击或发生事件的元素)。
在所有(synthetic)DOM事件处理程序中,React也会发生这种情况。
因此,如果我们希望方法的上下文始终指向React组件的实例,则可以使用instance方法。
另一种限制上下文但不使用需要Babel的特殊instance方法语法的方式是通过创建一个新函数来直接从类(原型)方法创建一个实例方法,并绑定上下文(使用Function.prototype.bind):
class A {
constructor() {
this.methodOnInstance = this.methodOnPrototype.bind(this);
}
methodOnPrototype() { return this; }
}
const instance = new A();
console.log(
instance.methodOnInstance() === instance.methodOnPrototype(),
instance.methodOnPrototype() === instance
);
这使我们能够通过当前可用的工具(ES2017及以下版本)达到与使用特殊实例方法语法相同的结果。
如果出于某种原因,我们想要一个始终绑定到不是该类实例的东西的方法,我们也可以这样做:
class A {
constructor() {
this.method = this.method.bind(console);
}
method() { return this; }
}
const instance = new A();
console.log(
instance.method() === console
);
this
)方法上使用bind
。 - Bergi