从名称创建一个没有eval的对象

时间:2018-03-13 21:44:59

标签: javascript node.js object this

我需要在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函数,我将不胜感激。

4 个答案:

答案 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语句,它也可以正常工作。无论什么更清洁。