我需要在Node.js中从其名称创建一个对象。我怎么能这样做(不使用eval)?
例如,我尝试了类似下面的代码,但是在“人是未知的”上失败了。 我想它与上下文有关(这个)。我尝试了bind / call / apply函数,但没有用。
module.export = {
class Person = {/*....*/};
var createObject = function(name) {
return Function('return new ' + name + '();')();
};
const p1 = new Person(); // works
const p2 = eval('return new Person();'); // works, but has security issues
const p3 = createObject('Person'): // doesn't work.
}:
如果您能告诉我如何正确编写createObject函数,我将不胜感激。
答案 0 :(得分:3)
为什么不创建可创建对象的地图并对其进行查找?
即:
const creatableObjects = {
'Person': Person,
'SomethingElse': SomethingElse
}
const config = getConfig();
const createdObject = new (creatableObjects[config.objectName])();
答案 1 :(得分:1)
为构造函数创建名称映射:
const permittedTypes = new Map([
['Person', Person],
…
]);
const configuredType = 'Person';
const p1 = new (permittedTypes.get(configuredType));
答案 2 :(得分:0)
传递给Function
的内容无法访问调用构造函数的作用域中定义的变量。
请参阅source。
使用Function构造函数创建的函数不会为其创建上下文创建闭包;它们总是在全球范围内创建。运行它们时,它们只能访问自己的局部变量和全局变量,而不能访问调用Function构造函数的范围。这与使用eval和函数表达式的代码不同。
虽然我很想知道你的用例是什么。 (我想我的答案没有正确回答你的问题。它只是解释了你收到错误的原因)
答案 3 :(得分:0)
使用eval()
或new Function()
任意访问变量可能会导致安全问题,并且当范围问题出现问题时,并不是那么可靠。
你可以做的是使用一个带有键映射到不同类的对象,然后使用你想要的特定键引用对象,如下所示:
const classes = {
Person: class Person {/* ... */},
Dog: class Dog {/* ... */},
Cat: class Cat {/* ... */},
}
function createObject(className) {
return new classes[className]()
}
const p = createObject('Person') // returns a person
其中一条评论也提出了一个switch语句,它也可以正常工作。无论什么更清洁。