英文:
Create JS classes dynamically while looping through object
问题
Here's the translated code snippet without the comments:
// function for dependency injection
addNumbers = (numbers) => {
let result = 0;
numbers.forEach((number) => {
result = result + number;
})
console.log(`\nThe result is ${result}`);
}
// class without parameters
class Log {
constructor() {
console.log('My only job is to log this text!\n');
}
}
// class with parameters
class Greeting {
constructor(params) {
this.sayHello(params);
}
sayHello(params) {
for (const [key, name] of Object.entries(params)) {
console.log(`Hello ${name}, nice to meet you!`);
}
}
}
// class with parameters and dependency injection
class Addition {
constructor(params) {
this.injectedMethod = params['dependency'];
this.injectedMethod(params['numbers']);
}
}
classParams = {
Log: '',
Greeting: {
name1: 'Alice',
name2: 'Bob'
},
Addition: {
numbers: [1, 2, 3, 4, 5],
dependency: addNumbers
}
}
// I'd like to have a loop that replaces the following code and iterates through classParams, creating the classes with their respective parameters
new Log();
new Greeting(classParams['Greeting']);
new Addition(classParams['Addition']);
And the code you tried to use, with some adjustments:
for (const [object, params] of Object.entries(classParams)) {
if (typeof window[object] === 'function') {
new window[object](params);
}
}
This adjusted code should help you create instances of classes based on the values in the classParams
object.
英文:
I'd like to create some kind of factory to automate the process of creating JS classes. The factory should loop through an object that contains classes names and their respective parameters. The following simplified code sample hopefully demonstrates what I mean:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
// function for dependency injection
addNumbers = (numbers) => {
let result = 0;
numbers.forEach((number) => {
result = result + number;
})
console.log(`\nThe result is ${result}`);
}
// class without parameters
class Log {
constructor() {
console.log ('My only job is to log this text!\n');
}
}
// class with parameters
class Greeting {
constructor(params) {
this.sayHello(params);
}
sayHello(params) {
for (const [key, name] of Object.entries(params)) {
console.log(`Hallo ${name}, nice to meet you!`);
}
}
}
// class with parameters
// and dependency injection
class Addition {
constructor(params) {
this.injectedMethod = params['dependency'];
this.injectedMethod(params['numbers']);
}
}
classParams = {
Log: '',
Greeting: {
name1: 'Alice',
name2: 'Bob'
},
Addition: {
numbers: [1, 2, 3, 4, 5],
dependency: addNumbers
}
}
// Here comes the critical part:
// I'd like to have a loop that replaces the
// following code and iterates through
// classParams, creating the classes with
// their respective parameters
new Log();
new Greeting(classParams['Greeting']);
new Addition(classParams['Addition']);
<!-- end snippet -->
I tried something like
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
for (const [object, params] of Object.entries(classParams)) {
new [object](params);
}
<!-- end snippet -->
.. but that won't work because inside the loop I don't get the class as an object but only as a string. I tried some things I found online, but the best I could achive was having no errors - but having no working classes either.
What am I getting wrong?
答案1
得分: 1
以下是翻译好的代码部分:
const addNumbers = e => {
let o = 0;
e.forEach(e => {
o += e
}), console.log(`
结果是 ${o}`)
};
class Log {
constructor() {
console.log("我的唯一工作是记录这个文本!\n")
}
}
class Greeting {
constructor(e) {
this.sayHello(e)
}
sayHello(e) {
for (let [o, t] of Object.entries(e)) console.log(`Hallo ${t}, 很高兴见到你!`)
}
}
class Addition {
constructor(e) {
this.injectedMethod = e.dependency,
this.injectedMethod(e.numbers)
}
}
const classParams = {
Log: "",
Greeting: {
name1: "Alice",
name2: "Bob"
},
Addition: {
numbers: [1, 2, 3, 4, 5],
dependency: addNumbers
}
};
const classes = {
Log,
Greeting,
Addition
};
for (const [k, v] of Object.entries(classParams)) {
new classes[k](v)
}
英文:
You can put all the classes into an object and use bracket notation to access classes by name using it.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const addNumbers=e=>{let o=0;e.forEach(e=>{o+=e}),console.log(`
The result is ${o}`)};class Log{constructor(){console.log("My only job is to log this text!\n")}}class Greeting{constructor(e){this.sayHello(e)}sayHello(e){for(let[o,t]of Object.entries(e))console.log(`Hallo ${t}, nice to meet you!`)}}class Addition{constructor(e){this.injectedMethod=e.dependency,this.injectedMethod(e.numbers)}}const classParams={Log:"",Greeting:{name1:"Alice",name2:"Bob"},Addition:{numbers:[1,2,3,4,5],dependency:addNumbers}};
const classes = {Log, Greeting, Addition};
for (const [k, v] of Object.entries(classParams)) {
new classes[k](v);
}
<!-- end snippet -->
答案2
得分: 1
Object
s only use strings for keys
Object
类只使用字符串作为键。
Unfortunately, JavaScript doesn't have support for values as keys with the Object
class.
不幸的是,JavaScript不支持将值用作Object
类的键。
There are, however, many options available to store classes with an argument or arguments to call them with.
然而,有许多选项可用于存储带有参数的类以及调用它们的参数。
Using an Object
and eval
to get the class
使用Object
和eval
来获取类
This is a safe usage of eval
, so no need to worry about that.
这是对eval
的安全使用,所以不需要担心。
Using an Array
or a Map
to store the class itself
使用Array
或Map
来存储类本身
Using one Object
to store the classes and another to store the arguments
使用一个Object
来存储类,另一个来存储参数
Sidenote
附注
If your constructor has multiple parameters or no parameters, I would recommend using an array to hold the arguments and using the spread syntax (i.e. ...
) to pass the arguments to the class.
如果您的构造函数有多个参数或没有参数,我建议使用数组来保存参数,并使用扩展语法(即...
)将参数传递给类。
Also if you need to create multiple of the same class with different arguments, I would recommend the Array
technique as shown above.
此外,如果您需要创建具有不同参数的多个相同类的实例,我建议使用上面所示的Array
技术。
英文:
Object
s only use strings for keys
Unfortunately, JavaScript doesn't have support for values as keys with the Object
class. There are, however, many options available to store classes with an argument or arguments to call them with. Below is a non-exhaustive list of such:
Using an Object
and eval
to get the class
This is a safe usage of eval
, so no need to worry about that.
class Example { constructor(arg) { console.log(arg) } }
const classesToGenerate = {
Example: 'Hello World'
}
for (const className in classesToGenerate) {
new (eval(className))(classesToGenerate[className])
}
Using an Array
or a Map
to store the class itself
class Example { constructor(arg) { console.log(arg) } }
let classesToGenerate = new Map([
[Example, 'Hello World!']
])
classesToGenerate.forEach((arg, Class) => {
new Class(arg)
})
// Using an Array is barely different but probably more appropriate
classesToGenerate = [
[Example, 'Hello World!']
]
classesToGenerate.forEach(([Class, arg]) => {
new Class(arg)
})
Using one Object
to store the classes and another to store the arguments
Credit goes to @Unmitigated for this technique.
class Example { constructor(arg) { console.log(arg) } }
const classesToGenerate = {
classes: { Example },
args: { Example: 'Hello World' }
}
for (const className in classesToGenerate.classes) {
new classesToGenerate.classes[className](classesToGenerate.args[className])
}
Sidenote
If your constructor has multiple parameters or no parameters, I would recommend using an array to hold the arguments and using the spread syntax (i.e. ...
) to pass the arguments to the class.
Also if you need to create multiple of the same class with different arguments, I would recommend the Array
technique as shown above.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论