JavaScript - 动态加载 class 并创建具有特定属性的新实例
JavaScript - Dynamically loading a class and creating new instance with specific properties
我有一个 Node.js v11.11.0 应用程序。在此应用中,我的文件结构如下:
./src
/animals/
animal.js
tiger.js
koala.js
index.js
如上图,我在animals
目录下定义了三个class。随着时间的推移,我打算添加更多具有更复杂逻辑的动物。此时我的classes是这样定义的:
animal.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;
tiger.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;
koala.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;
我正在尝试根据用户输入的内容动态创建其中一个 class 的实例。例如,我这样做:
index.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);
});
如果我 运行 并输入 ./animals/tiger.js
,我会得到一个错误。错误显示:Property description must be an object
。我不明白这一点。 Tiger
和 Koala
都扩展了 Animal
。同时,由于我的列表是动态的,我需要输入文件路径和动态加载 class 的自由格式选项。因此,我不能使用 所示的方法,它专门列出了 Class 名称。
如何动态加载 class 并创建具有特定属性的 class 实例?
Object.create
的第二个参数与您传递给 Object.defineProperties
的参数相同,因此您的 properties
无效。而是使用 Object.assign:
Object.assign(Object.create(Animal.prototype), properties)
但是你为什么不直接调用构造函数呢?
new Animal(properties)
其次:
properties = properties || {};
可能是:
this.properties = properties || {};
而且我不建议动态 require
,尤其是不要从用户输入的值,而是创建一个查找对象:
const AnimalByName = {
Bear: require("./Bear"),
//...
};
const instance = new AnimalByName[name](properties);
我有一个 Node.js v11.11.0 应用程序。在此应用中,我的文件结构如下:
./src
/animals/
animal.js
tiger.js
koala.js
index.js
如上图,我在animals
目录下定义了三个class。随着时间的推移,我打算添加更多具有更复杂逻辑的动物。此时我的classes是这样定义的:
animal.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;
tiger.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;
koala.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;
我正在尝试根据用户输入的内容动态创建其中一个 class 的实例。例如,我这样做:
index.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);
});
如果我 运行 并输入 ./animals/tiger.js
,我会得到一个错误。错误显示:Property description must be an object
。我不明白这一点。 Tiger
和 Koala
都扩展了 Animal
。同时,由于我的列表是动态的,我需要输入文件路径和动态加载 class 的自由格式选项。因此,我不能使用
如何动态加载 class 并创建具有特定属性的 class 实例?
Object.create
的第二个参数与您传递给 Object.defineProperties
的参数相同,因此您的 properties
无效。而是使用 Object.assign:
Object.assign(Object.create(Animal.prototype), properties)
但是你为什么不直接调用构造函数呢?
new Animal(properties)
其次:
properties = properties || {};
可能是:
this.properties = properties || {};
而且我不建议动态 require
,尤其是不要从用户输入的值,而是创建一个查找对象:
const AnimalByName = {
Bear: require("./Bear"),
//...
};
const instance = new AnimalByName[name](properties);