2011-07-06 18 views
3

拋開了罕見的情況,在JavaScript中使用了eval() is considered bad practiceJavaScript,Eval和新 - 窮人的工廠

我剛剛遇到了一段代碼,它接受一個字符串並按該類型名稱構造一個對象。錯誤檢查,業務邏輯和上下文這樣做的切除,這裏是什麼樣子:

function factory(klass) { 
    eval("var obj = new " + klass + "()"); // Is there a better way? 
    return obj; 
} 

是否有更好(更安全,更清潔,和/或更快)的方式來實現類創建不使用eval

我在尋找一個通用方式來創建一個類名稱。例如,想象一下,例如,代碼的另一部分動態加載JavaScript文件,生成代碼或允許用戶擴展,但是代碼的其他部分需要創建該類,而不需要工廠具有其先前的知識存在。

+0

錯誤檢查等。爲了在StackOverflow上創建一個簡潔的例子而刪除了它 - 不是。 –

+0

沒有深入瞭解它背後的原因,克拉斯是一個字符串。重要的是找到一種方法來做邏輯等價物,使用相同的輸入,而不使用eval()來拉開特技。 –

回答

5

你可以用你的工廠對象登記類和不是由字符串名稱創建它們:

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](); 
} 
+1

我真的想給這個分裂信貸。大衛Titarenco在他的評論中表示,沒有評估就不可能做我想做的事情。 Alexei Levenkov設法讓下一個最接近的東西,根據需要採取一個字符串,從工廠對象返回類。所以我接受這是迄今爲止提出的避免使用eval()的最佳方式。感謝大家。 –

1

你不需要評估。您可以簡單地傳遞對象而不是其名稱,並使用var obj = new klass()。 Voilà

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

function C() {...} 
C.prototype = {...} 

factory(C); 
+1

在我看來他們*想要*傳遞一個變量的名字,一個字符串。這就是問題所在。 – katspaugh

+0

@katspaugh這個問題清楚地說明:「是否有更好的(更安全,更清潔和/或更快)的方法來__完成類的創建而不使用eval?__」。閱讀理解 –

+0

然而,有一種方法可以完成類的創建,提供了一個名稱和一個名稱空間,括號表示法。這與原來的功能更接近一點,你不覺得嗎? – katspaugh

3

這裏有一個錯誤檢查是重要的,你不應該刪除它的情況。說我們一起去@加比的「硬工廠」解決方案:

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())都是有用的,並且是語言的一部分是很重要的。有些人過度使用或者在錯誤的環境中使用它並不意味着它不是一個非常強大的工具。

+0

另外,你應該明確說明'eval'要求你小心輸入:如果'klass'類似'function(){};/*你的惡意代碼* /(function(){})',你遇到了一些麻煩 –

+0

所以,我認同的錯誤檢查,但不是與eval有關的問題的一部分,這個答案證實了這一點這是使用eval的幾個可接受的情況之一,並且這是實現此功能的正確方法? –

+0

如果你問是否有一種方法可以將字符串傳遞給一個函數,然後獲取字符串的對象表示,那麼不需要,沒有eval就沒有辦法做到這一點。 –