简体   繁体   English

将ES6类存储在变量中,并通过Object.Create对其进行实例化

[英]Store ES6 class in variable and instance it through Object.Create

I'm currently needing to pass a class through a variable to a function which dynamically calls their constructor and so on. 我当前需要通过变量将传递给函数,该函数动态调用其构造函数,依此类推。 Short example: 简短示例:

class MyClass {
  constructor ($q) {
    console.log($q);
  }

  expose () {
    return {};
  }
}

const myclass = function () {
  // My concern is this ------.
  // I need to pass it        |
  // as a variable           \|/
  //                          '
  let obj = Object.create(MyClass.prototype);
  obj.constructor.apply(obj, arguments);
  return {}; // other stuff goes here
};
myclass.$inject = ['$q'];
export {myclass};

My idea is to pass MyClass as a variable, to have it this way: 我的想法是将MyClass作为变量传递,以这种方式进行:

const myclass = function (classVariable) {
  let obj = Object.create(classVariable.prototype);
  obj.constructor.apply(obj, arguments);
  return {}; // other stuff goes here
};

So that I can call it like let newclass = myclass(MyClass); 这样我就可以像let newclass = myclass(MyClass);这样来称呼它let newclass = myclass(MyClass); . This way if I have different classes (MyClass2, MyClass3, and so on) I don't have to repeat code in each file. 这样,如果我有不同的类(MyClass2,MyClass3等),则不必在每个文件中重复代码。 If I try to do it this way though, Chrome throws an error saying that it cannot use a class as variable or something like that. 但是,如果我尝试这样做,Chrome会抛出一个错误,提示它不能将类用作变量或类似的东西。

So, what would be the best approach to do this and avoid repeating code? 那么,什么是避免重复代码的最佳方法呢? it's actually a redesign I'm working on to avoid the copy-paste disaster made by someone else I need to fix. 实际上,这是我正在进行的重新设计,以避免需要修复的其他人造成的复制粘贴灾难。 Thanks in advance! 提前致谢!

I think your confusion is that you think that class constructors cannot be referenced by variables. 我认为您的困惑是,您认为类构造函数不能被变量引用。 They can, they're just functions. 他们可以,只是功能而已。 So: 所以:

 class Foo { message() { console.log("I'm a Foo"); } } class Bar { message() { console.log("I'm a Bar"); } } function test(C) { let obj = new C(); obj.message(); // "I'm a Foo" or "I'm a Bar", depending on // whether Foo or Bar was passed in } test(Foo); test(Bar); 

Your pattern of calling var obj = Object.create(X.prototype) followed by X.apply(obj, /*...args here...*/) would work in ES5 and earlier, but ES2015's classes don't allow it. 您的调用var obj = Object.create(X.prototype)后跟X.apply(obj, /*...args here...*/)在ES5和更早版本中可以使用,但是ES2015的类不允许它。 To construct instances from them, you have to use the new operator. 要从它们构造实例, 必须使用new运算符。 The reason for that has to do with subclassing and setting new.target , so that if the instance has reason to create new instances (as Promise does), it can do that in an unambiguous way. 这样做的原因与子类化和设置new.target ,因此,如果实例有创建新实例的理由(如Promise所做的那样),则它可以明确地做到这一点。

Which seems like it could be a step back, but if for some reason you have the constructor arguments as an array rather than discrete items, spread notation lets you use new anyway: 似乎可以退后一步,但是如果由于某种原因您将构造函数参数作为数组而不是离散项,则可以使用扩展符号使用new

let obj = new C(...args);

So if you need a generic function that accepts a class constructor and an array of arguments and needs to return an instance of that class using those arguments, it would look like this: 因此, 如果您需要一个接受类构造函数和参数数组的泛型函数,并且需要使用这些参数返回该类的实例,则它看起来像这样:

function createInstanceOf(C, args) {
    return new C(...args);
}

I believe what you are looking for is a closure : 我相信您正在寻找的是封闭

function makeFactory(constructor) {
  return function(...args) {
    let obj = new constructor(...args);
    return {}; // other stuff goes here
  };
}
const myclass = makeFactory(MyClass);
// then use
myClass().expose() // or whatever you were going to do with it

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM