JavaScript、Eval和New——穷人的工厂

JavaScript, Eval, and New -- poor man's factory

本文关键字:工厂 New Eval JavaScript      更新时间:2023-09-26

除了少数情况外,eval()在JavaScript中被认为是不好的做法。

我刚刚遇到一段代码,它接受一个字符串并按照该类型名构造一个对象。删除了错误检查、业务逻辑和执行此操作的上下文,如下所示:

function factory(klass) {
  eval("var obj = new " + klass + "()"); // Is there a better way?
  return obj;
}
有没有更好(更安全,更干净,和/或更快)的方法来完成类创建而不使用eval?

我正在寻找一个通用的的方式来创建一个类的名称

。例如,想象一下,代码的另一部分动态加载JavaScript文件,生成代码,或允许用户扩展,但随后代码的另一部分需要在工厂不知道其存在的情况下生成该类。

您可以在工厂对象中注册类,然后通过字符串名称创建它们:

var allClasses = [];
allClasses["MyClass"] = function(){return new MyClass();}
allClasses["MyStruct"] = function() {return {F1:"", F2:42};}
function factory(klass) 
{
    if (!allClasses[klass]) throw "Bad name!";
    return allClasses[klass]();
}

在这种情况下,错误检查很重要,您不应该删除它。如果我们采用@Gabi的"硬工厂"解决方案:

function hardfactory(klass) {
  var obj = new klass();
  return obj;
}
try {
var x = hardfactory(asdf); // this will break unless
                           // we wrap every single hardfactory() call in a try-catch
} catch (err) {
    console.log(err);
} // who wants to do this every time we invoke hardfactory? not I

现在让我们看看你原来的"软工厂"解决方案:

function softfactory(klass) {
  try {
      eval("var obj = new " + klass + "()");
  } catch (err) {
      console.log(err);
  }
  return obj;
}
var y = softfactory("asdf"); // this will not break
                             // since we do the try catch inside the softfactory()

在这种情况下,eval()调用是有充分保证的。重要的是要理解每种语言结构(是的,甚至是eval())都是有用的,并且是语言的一部分。有些人过度使用它或在错误的情况下使用它,但这并不意味着它在正确的情况下不是一个非常强大的工具。

不需要eval。您可以简单地传递对象而不是其名称,并使用var obj = new klass()。瞧

function factory(klass) {
  var obj = new klass();
  return obj;
}
function C() {...}
C.prototype = {...}
factory(C);