【问题标题】:ES6 - declare a prototype method on a class with an import statementES6 - 使用 import 语句在类上声明原型方法
【发布时间】:2015-12-18 10:17:22
【问题描述】:

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

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

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

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

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

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

这可行吗?

【问题讨论】:

    标签: javascript class import prototype ecmascript-6


    【解决方案1】:

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

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

    但是,与从类语法创建的方法相反,这使得方法可枚举。所以你可能想改用Object.defineProperty

    【讨论】:

    • 感谢您的回答。我明白我可以做到这一点。我可能没有明确说明我希望在 ES6 中保持新的导入语法,以及 ES6 类声明原型方法的方式(如上)。这可能吗?
    • FWIW,为了简单起见,我在这里只使用了require。没有什么能阻止您使用import 来获取价值。至于类语法,不,ES6 没有提供这样做的方法(除了委托给函数的变通方法,如另一个答案中所示)。有一个 ES7 stage 0 proposal 用于类属性,你可以在其中写 class Foo { getColor = require('./getColor'); },但同样,在 ES6 中没有类似的东西。
    • @SheedySheedySheedy 如果您想要 ES6 导入,请参阅我的回答。但是,导入是提升的,因此您必须在最顶部声明​​它们。
    • 我想知道,为什么是静态方法。超集原型(不在实例上)方法不是他们的目的吗...
    • @FelixKling 这个解决方案在反应中不起作用请查看这个stackoverflow.com/questions/40603632/…
    【解决方案2】:

    你仍然可以在class'原型上附加一个方法;毕竟,类只是“函数对象”的语法糖,这是使用函数构造对象的旧方法。

    既然你想使用 ES6,我将使用 ES6 导入。

    最小的努力,使用原型:

    import getColor from 'path/to/module';
    
    class Car {
        ...
    }
    
    Car.prototype.getColor = getColor;
    

    如您所见,您仍然使用原型属性来附加一个方法,如果您选择这样做的话。


    在类中调用模块的方法:

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

    import getColor from 'path/to/module';
    
    class Car {
        getColor () {
            return getColor.call(this);
        }
    }
    

    使用吸气剂

    您也可能有点棘手,并使用“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;
    

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


    ES2016 类属性

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

    import getColor from 'path/to/module';
    
    class Car {
        getColor = getColor;
    }
    

    带有类属性的可选绑定

    如果您使用简写语法来设置属性,您将不必绑定方法(设置是作为属性更改“this”所指的内容,本质上是自动绑定它),但你当然可以,如果你选择(如果你想绑定其他东西):

    getColor = getColor.bind(this);
    

    【讨论】:

    • 不,你不需要绑定函数。仍然是设置this的方法调用。
    • 对于在添加到原型时遇到绑定问题的任何人,这些必须是常规的function 声明。这意味着您不能使用导入的箭头函数。
    • @GoogleMac 正是因为如此,我个人认为应该为回调保留箭头,词法绑定实际上是有意义的。独立的 function 声明应该在其他任何地方使用(但这只是我个人的喜好)
    【解决方案3】:

    如果您有兴趣,我已经开发了一个小模块,可以将具有不同数量参数的函数绑定到类方法:https://github.com/ngryman/to-method

    const toMethod = require('to-method');
    
    function Car(color) {
      this.color = color;
    }
    
    toMethod(Car, { getColor: require('./getColor') });
    

    【讨论】:

      猜你喜欢
      • 2021-11-28
      • 2017-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-24
      • 2011-01-09
      • 2017-12-12
      • 1970-01-01
      相关资源
      最近更新 更多