JavaScript - 动态加载类并创建具有特定属性的新实例

use*_*554 3 javascript es6-class

我有一个 Node.js v11.11.0 应用程序。在此应用程序中,我的文件结构如下:

./src
  /animals/
    animal.js
    tiger.js
    koala.js
  index.js
Run Code Online (Sandbox Code Playgroud)

如上所示,我在animals目录中定义了三个类。随着时间的推移,我打算添加更多具有更复杂逻辑的动物。此时,我的类定义如下:

动物.js

'use strict';

class Animal {
  constructor(properties) {
    properties = properties || {};

    this.kind = 'Unknown';
  }

  eat(foods) {
    for (let i=0; i<foods.length; i++) {
      console.log(`Eating ${foods[i]}`);
    }
  }
}

module.exports = Animal;
Run Code Online (Sandbox Code Playgroud)

老虎.js

'use strict';

const Animal = require('./animal');

class Tiger extends Animal {
  constructor(properties) {
    super(properties);

    this.kind = 'Tiger';
  }

  eat(foods) {
    for (let i=0; i<foods.length; i++) {
      if (foods[i].kind === 'meat') {
        console.log(`Eating ${foods[i]}`);
      }
    }
  }
}

module.exports = Tiger;
Run Code Online (Sandbox Code Playgroud)

考拉.js

'use strict';

const Animal = require('./animal');

class Koala extends Animal {
  constructor(properties) {
    super(properties);

    this.kind = 'Koala';
  }

  eat(foods) {
    for (let i=0; i<foods.length; i++) {
      if (foods[i].kind === 'plant') {
        console.log(`Eating ${foods[i]}`);
      }
    }
  }
}

module.exports = Koala;
Run Code Online (Sandbox Code Playgroud)

我正在尝试根据用户输入的内容动态创建这些类之一的实例。例如,我正在这样做:

索引.js

const readline = require('readline').createInterface({
  input: process.stdin,
  output: process.stdout
})

readline.question('What animal file do you want to load?', (fname) => {
  let properties = {
    name: 'My Pet'
  };

  let Animal = require(fname);
  let pet = Object.create(Animal.prototype, properties);
});
Run Code Online (Sandbox Code Playgroud)

如果我运行它并输入./animals/tiger.js,我会收到错误。错误说:Property description must be an object。我不明白这一点。两者TigerKoala延伸Animal. 同时,由于我的列表是动态的,我需要输入文件路径并动态加载类的自由格式选项。因此,我无法使用此处显示的方法,该方法专门列出了类名称。

如何动态加载类并创建具有特定属性的该类的实例?

Jon*_*lms 5

的第二个参数与Object.create您传递给 的参数相同Object.definePropertiesproperties因此您的参数无效。而是使用 Object.assign:

 Object.assign(Object.create(Animal.prototype), properties)
Run Code Online (Sandbox Code Playgroud)

但为什么不直接调用构造函数呢?

 new Animal(properties)
Run Code Online (Sandbox Code Playgroud)

其次这个:

 properties = properties || {};
Run Code Online (Sandbox Code Playgroud)

可能的目的是:

 this.properties = properties || {};
Run Code Online (Sandbox Code Playgroud)

我不建议动态地require创建一个查找对象,尤其是不要根据用户输入的值:

 const AnimalByName = {
   Bear: require("./Bear"),
   //...
 };

 const instance = new AnimalByName[name](properties);
Run Code Online (Sandbox Code Playgroud)

  • @al-un 有多种原因,其中之一是以下动物: `../.../../secret/directory/password.json` ...此外,还有很多情况下 require 会崩溃或者创建一个无效的 Animal,这会在以后引起麻烦。 (2认同)