I have a Node.js v11.11.0 app. In this app, my files are structured like the following:
./src
/animals/
animal.js
tiger.js
koala.js
index.js
As shown above, I have three classes defined in the animals directory. Over time, I intend to add additional animals with more complex logic. At this time, my classes are defined like so:
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;
I am trying to dynamically create an instance of one of these classes based on what the user enters. For example, I'm doing this:
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);
});
If I run this and enter ./animals/tiger.js, I get an error. The error says: Property description must be an object. I don't understand this. Both Tiger and Koala extend Animal. At the same time, as my list will be dynamic, I need the free form option of typing a file path and dynamically loading the class. For that reason, I can't use the approach shown here, which specifically lists the Class names.
How do I dynamically load a class and create an instance of that class with specific properties?
The second argument to Object.create is the same argument you would pass to Object.defineProperties, your properties is therefore invalid. Instead use Object.assign:
Object.assign(Object.create(Animal.prototype), properties)
But why don't you just call the constructor?
new Animal(properties)
Secondly this:
properties = properties || {};
is probably intended to be:
this.properties = properties || {};
And I wouldn't recommend to dynamically require, especially not from a user entered value, instead create a lookup object:
const AnimalByName = {
Bear: require("./Bear"),
//...
};
const instance = new AnimalByName[name](properties);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With