2011-08-23 132 views
7

JavaScript的新手在这里,我要通过在工作中的一些js代码,当我遇到对象创建一个辅助功能,它是这样进行的JavaScript对象创建

createElement = function(name, data){ 
    if(name == TYPES.TEXT){ 
    return new Text(data); 
    } 
    else if(name == TYPES.WORD){ 
    return new Word(data); 
    } 
    else if(name == TYPES.PARAGRAPH){ 
    return new Paragraph(data); 
    } 
    else if(name == TYPES.TABLE){ 
    return new Table(data); 
    } 
    <list goes on and on and on... > 
} 

,而这并完成这项工作我会来到想知道是否有更好,更清洁的写作方式。

+0

你可能会感兴趣的[开关结构(https://developer.mozilla.org/en/JavaScript/Reference/Statements/switch)... – DaveRandom

回答

9

你是对的,过多if..thenswitch逻辑是code smell,几乎总是可以重构成更优雅的东西。在这种情况下,基于名称的工厂可重构与键作为名称和值作为函数的字典返回

var dictionary = {}; 
dictionary[TYPES.TEXT] = Text; 
dictionary[TYPES.WORD] = Word; 
dictionary[TYPES.PARAGRAPH] = Paragraph; 
dictionary[TYPES.TABLE] = Table; 

createElement = function(name, data){ 
    return new dictionary[name](data); 
} 

活生生的例子:http://jsfiddle.net/KkMnd/

编辑:这行createElement方法可以/应该首先检查是否为传入的TYPES.*配置了一些内容。一种好方法是在尝试调用该方法之前检查字典中是否存在元素。

return (typeof dictionary[name] == 'function') ? new dictionary[name](data) : some_default_value; 
+0

我喜欢他的回答更好。 – Prospero

+0

+1这个解决方案的另外一个好处是,如果你的'TYPES'需要扩展,你不需要改变任何*逻辑*来做到这一点,你必须做一个'switch'。 – peirix

+3

+1用于简化和提及此模式的名称(工厂模式)。我担心的是OP没有提到最后的“_else_”声明,你也应该在这里实现它,例如。 'return(typeof dictionary [name]!='undefined')? dictionary [name](data):something_goes_here;'(如果没有发现,只需用预期的结果替换'something_goes_here')。 – Tadeck

0

这将是一个更清洁,但在语义上使用switch语句相同。

function createElement(name,data){ 
switch(name) 
{ 
case TYPES.TEXT: 
    return new Text(data) 
    break; 
case TYPES.WORD: 
    return new WORD(data) 
    break; 
default: 
    // etc. code to be executed if no values match 
} 
}