javascript - ES6 类中的 constr.apply(this, args)

标签 javascript node.js oop constructor ecmascript-6

一段时间以来,我一直在使用以下函数来创建未知类的实例:

Kernel.prototype._construct = function (constr, args) {
  function F() {
    constr.apply(this, args); // EXCEPTION!
  }
  F.prototype = constr.prototype;
  return new F();
};

如果我使用原型(prototype),一切正常:

function Person(name, surname) {
  this.name = name;
  this.surname = surname;
}

var person = Kernel._construct(Person, ["name", "surname"]); // WORKS!

但是,有些人在 Node v4+ 中使用 ES6 原生类来使用我的库:

class Person {
  constructor(name, surname) {
    this.name = name;
    this.surname = surname;
  }
}

var person = Kernel._construct(Person, ["name", surname]); // EXCEPTION!

他们收到一个错误:

TypeError: Class constructors cannot be invoked without 'new'

我需要能够使用未知数量的参数调用构造函数。关于如何解决此问题的任何想法?

最佳答案

有多种方法可以做到这一点:

  1. 使用 Function对象的方法:

    Kernel.prototype._construct = function (constr, args) {
      return new (Function.prototype.bind.apply(constr, [null].concat(args)));
    };
    

    我们在这里 applying args 作为 bind 的参数.目标是拥有一个无需参数即可调用的函数,以便我们可以调用 new x()bind 为我们做了这个,但我们需要正确设置它。语法是:

    func.bind(thisArg[, arg1][, args2...])
    // calling the results from the above is like
    // thisArg.func(arg1, arg2...);
    

    我们想使用 constr 作为绑定(bind)函数,args 中的项目作为参数。我们不关心 thisArg。为此,我们需要将 args 数组“转换”为参数。 apply 调用执行此操作:

    func.apply(thisArg[, args]);
    // calling the results from the above is like
    // thisArg.func(args[0], args[1]...);
    

    apply其实就是在调用bind。第一项 [null] 很重要,因为我们要调用 bind,其中 thisArgnull - 就像这个:constr.bind(null, args[0], args[1]...)

  2. 使用 ES2015 Spread operator :

    Kernel.prototype._construct = function (constr, args) {
      return new constr(...args);
    };
    

    这样就简单多了,但是有两个问题:

    1. 它需要 ES2015 支持,甚至最新的 Node (v4.2.1) 也需要一个标志 (--harmony_spreadcalls)。
    2. 如果不支持,这将产生语法错误,您甚至不能有条件地这样做,除非使用动态脚本 (eval()/new Function(...) ) - 不建议这样做。
  3. 使用 Reflect内置对象。

    Kernel.prototype._construct = function (constr, args) {
        return Reflect.construct(constr, args);
    };
    

    这也很简单,但在支持方面更落后(基本上你必须使用 babel)。

关于javascript - ES6 类中的 constr.apply(this, args),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33193310/

相关文章:

oop - 去 "polymorphism"

javascript - 警报框陷入无限循环

javascript - 在对话框上使用 .replaceWith()。怎么了?

javascript - 如何根据 URL 在 polymer 元素上执行 select() 方法?

javascript - 导航栏过渡动画仅在向上滚动时

node.js - 创建 GCP 存储桶时指定 projectId

c# - 当需要不同数量和类型的参数时如何创建 Action 委托(delegate)列表

Scala 类型参数不符合类型参数范围

node.js - 尝试为 Express 应用启动 NodeJS 时出现 Openshift 错误

javascript - Jasmine + karma : 'expect' was used when there was no current spec error, 但为什么呢?