ES6 - 使用 import 语句在 class 上声明原型方法

ES6 - declare a prototype method on a class with an import statement

我正在使用 ES6 类。我希望能够做到这一点:

function Car(color) {
  this.color = color;
};

Car.prototype.getColor = require('./getColor');

其中 get color 是一个导出函数。即我希望能够从外部文件导入一个函数并将其设置为 ES6 Class 上的原型方法。这就是我所说的那种语法:

class Car {
  constructor(color) {
    this.color = color;
  }

  getColor() {} // I want to import this function from './getColor', as above
}

这可行吗?

是的。 class 语法只是(非常复杂的)构造函数的语法糖。所以 Car 仍然是一个带有 prototype 属性 的函数,你可以做同样的事情:

import getColor from './getColor';
// ...
Car.prototype.getColor = getColor;

然而,这使得方法可枚举,而不是从 class 语法创建的方法。所以你可能想改用 Object.defineProperty

您仍然可以在 class' 原型上附加方法;毕竟,classes 只是 "functional object" 的语法糖,这是使用函数构造对象的旧方法。

既然你想用 ES6,我就用 ES6 导入。

最小的努力,使用原型:

import getColor from 'path/to/module';

class Car {
    ...
}

Car.prototype.getColor = getColor;

如您所见,您仍然使用原型 属性 来附加方法,如果您愿意的话。


在 class' 方法中调用模块:

或者,如果您不想使用原型 属性,您始终可以使用模块中的方法 return 函数:

import getColor from 'path/to/module';

class Car {
    getColor () {
        return getColor.call(this);
    }
}

使用 Getter

您也可以使用 "getter" 以不同的方式实现此目的。

import getColor from 'path/to/module';

class Car {
    get getColor () { return getColor.bind(this) }
}

然后您只需调用 myInstanceOfCar.getColor()

即可使用它

或者更语义化的用法 getter:

class Car {
    get color () { return getColor.call(this) }
}

// ...

const color = myInstanceOfCar.color;

请记住,getters/setters 不能与您在构造函数中设置的属性同名。当您尝试使用 setter 设置相同的 属性 时,您将最终超过无限递归的最大调用堆栈。 示例:set foo (value) { this.foo = value }


ES2016 Class 属性

如果你是 using Babel to transpile (and are using experimental proposals), and want to use some ES2016, you can use the following syntax(但请记住,这会将方法直接应用于对象,而不是在原型上设置):

import getColor from 'path/to/module';

class Car {
    getColor = getColor;
}

带有 class 属性的可选绑定

如果您使用 shorthand 语法来设置 属性, 您将不必绑定方法 (设置为 属性 改变了 "this" 所指的内容,本质上是自动绑定它),但你当然可以,如果你选择这样做(比如如果你想绑定其他东西):

getColor = getColor.bind(this);

如果您有兴趣,我开发了一个小模块来将具有各种参数的函数绑定到 class 方法:https://github.com/ngryman/to-method.

const toMethod = require('to-method');

function Car(color) {
  this.color = color;
}

toMethod(Car, { getColor: require('./getColor') });