2016-05-08 2 views
0

В моем Javascript у меня есть своего рода фабрика. В зависимости от переданной строки Я создаю новый экземпляр этой строки в качестве объекта. НапримерАльтернатива для использования eval в Javascript

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

Я не хочу использовать Eval здесь. Я мог бы использовать оператор switch в свойстве employeeType, но мне не нужны зависимости от необходимости знать тип employeeType.

Есть ли другой способ, как я мог это сделать?

+2

Можете ли вы создать глобальный реестр типов сотрудников, например. 'var employeeTypes = {" 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; 
} 

Теперь ваши основные функции, getEmployee и registerEmployeeType, могут быть объявлены сами по себе без какой-либо информации о зарегистрированных типах сотрудников. Они могут даже быть зарегистрированы из разных файлов сценариев при условии, что они выполняются после определяется 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

Hi p.s.w.g Благодарим вас за ввод. Это будет работать, но вызывающий на заводе не имеет тип employeeType как объект, только как строка. Это потому, что вызывающий объект из другого проекта имеет только массив строк. Завод вызывает другое приложение, в котором живут настоящие классы. –

+0

@ RalfD'hooge Именно это и дает мое решение. Фактически, единственная разница между вашей версией и моей версией заключается в том, что я включил проверку 'if', чтобы убедиться, что вызывающий абонент не сделал что-то странное, как call' getEmployee ("toString") '. –

+0

Я включил его в свой ответ, что именно благодаря вам у меня есть решение. И я также добавлю в свое приложение дополнительные чеки, как вы упомянули. –

0

Вы должны передать функции для employeeType вместо строки (или более классический - объект с фиксированным способом), а затем вызвать функцию вместо eval его.

+0

Бывают случаи, когда это не вариант. Например.если вы разбираете результат Json в форме '{" employees ": [{" name ":" Joe "," type ":" manager "}, {" name ":" Sally "," type ":" intern "}]}'. В какой-то момент вам нужно сопоставить строку '' manager '' с функцией 'Manager'. Но, предоставленный, ОП не сказал нам достаточно, чтобы узнать, является ли это одним из тех случаев. –

+0

Это случай p.s.w.g И фактически функции объекта живут в другом проекте –

0

Спасибо p.s.w.g Я нашел ответ. Я регистрирую типы перед моей фабрикой. Я все еще передаю тип как строку на свой завод, но посмотрю на зарегистрированные типы.

Так что все ваши комментарии.

function getEmployee (employeeType, department){ 
    var fn = registeredTypes[employeeType]; 
    return new fn(department); 
} 
Смежные вопросы