2016-05-08 254 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); 
}