2016-05-08 332 views
0

在我的Javascript我有一种工厂。 根据字符串的传递,我创建了一个新的字符串作为对象的实例。 例如在JavaScript中使用eval的替代方案

function getEmployee (employeeType, department){ 
     var fn = eval(employeeType); 
     return new fn(department); 
    } 

我不想在这里使用eval。 我可以在employeeType上使用switch语句,但我不想要知道employeeType的任何依赖关系。

有没有另外一种方法可以做到这一点?

+2

您可以创建员工类型的全局注册表,例如: 'var employeeTypes = {“manager”:Manager,“intern”:Intern}'?或者你会认为这是一种依赖性? –

+0

如果您事先不知道类型,那么'fn = window [employeeType]'是一种替代方案,但@ p.s.w.g的解决方案更安全。无论如何,不​​需要'evil()'。 – Amadan

+0

您是否可以不只是将employeeType作为工厂原型的对象? – Soren

回答

5

为了扩大对我原先的评论,每当我遇到这样的问题,一般的解决办法是建立某种形式的有效名称的全球注册的:

function Manager() { /* manager employee type */ } 
function Intern() { /* intern employee type */ } 

var registeredTypes = { 
    "manager": Manager, 
    "intern": Intern 
}; 

然后再编写功能:

function getEmployee (employeeType, department) { 
    if (!(employeeType in registeredTypes)) 
     throw "Invalid employee type: " + employeeType; 
    var fn = registeredTypes[employeeType]; 
    return new fn(department); 
} 

但是,如果你真的关心的依赖,你甚至可以有点进一步通过提供一个全球性的方法,以新员工类型添加到注册表中分离了这一点

function registerEmployeeType(employeeType, fn) { 
    if (employeeType in registeredTypes) 
     throw "Employee type already registered: " + employeeType; 
    if (typeof(fn) != "function") 
     throw "May only register employee types as functions: " + employeeType; 
    registeredTypes[employeeType] = fn; 
} 

现在,您的核心职能getEmployeeregisterEmployeeType可以自行声明,无需任何有关正在注册的员工类型的信息。他们甚至可以从不同的脚本文件注册,只要它们在之后运行之后,就可以定义registerEmployeeType。例如:

// core.js 
var registeredTypes = { }; 
function getEmployee (employeeType, department) ... 
function registerEmployeeType (employeeType, fn) ... 

// manager.js 
registerEmployeeType("manager", function() { /* manager employee type */ }); 

// intern.js 
registerEmployeeType("intern", function() { /* intern employee type */ }); 

// index.html 
<script src="core.js"></script> 
<script src="manager.js"></script> 
<script src="intern.js"></script> 
+0

嗨p.s.w.g 感谢您的意见。这会起作用,但工厂的调用者没有employeeType作为对象,只能作为字符串。 这是因为调用者来自另一个项目并且只有一个字符串数组。 工厂调用另一个应用程序,真正的类在哪里生活。 –

+0

@ RalfD'hooge这正是我的解决方案所提供的。事实上,你的版本和我的唯一区别在于我包含了一个'if'检查来确保调用者不会像调用'getEmployee(“toString”)''那样做一些奇怪的事情。 –

+0

我把它列入我的答案,这是感谢你我有解决方案。我会在你的申请中加入额外的支票。 –

0

你应该传递函数为employeeType而不是字符串(或多个古典 - 具有固定方法的对象),然后调用代替eval它的功能。

+0

有时候这不是一个选项。例如。如果以“{”employees“形式解析Json结果:[{”name“:”Joe“,”type“:”manager“},{”name“:”Sally“,”type“:”实习生“}]}'。在某些时候,您必须将字符串'“manager''映射到函数'Manager'。但是,OP没有告诉我们足够的知道这是否是其中的一个。 –

+0

这是实例p.s.w.g 而实际的对象函数存在于另一个项目中 –

0

感谢p.s.w.g我找到了答案。 我在工厂之前注册类型。 我仍然将该类型作为字符串传递给我的工厂,但在注册类型中查找它。

所以thx全部为您的意见。

function getEmployee (employeeType, department){ 
    var fn = registeredTypes[employeeType]; 
    return new fn(department); 
}