2010-07-09 136 views
3

我有一個功能,需要一個字符串對象的名字,我需要的功能,以創建具有相同的名稱作爲字符串動態對象創建

例如值的對象的新實例,

function Foo(){} 
function create(name){ 
    return new name(); 
} 
create('Foo'); //should be equivalent to new Foo(); 

雖然我知道這將是可能的通過評估,這將是很好的嘗試和避免使用它。我如果任何人有一個替代的想法也很感興趣的問題(下)


我有一個數據庫和一套(使用傳統OO方法)班,大約一個定義上的通用操作的每個表表。 (對於那些使用PHP的人,非常類似於Zend_Db)。由於一切都是基於最後一個結果異步執行任務可能導致非常縮進代碼

var table1 = new Table1Db(); 
table1.doFoo({ 
    success:function(){ 
     var table2 = new Table2Db(); 
     table2.doBar({ 
      notFound:function(){ 
       doStuff(); 
      } 
     }); 
    } 
}); 

顯而易見的解決方案是創建一個抽象的代碼的異步性的輔助方法。

Db.using(db) //the database object 
    .require('Table1', 'doFoo', 'success') //table name, function, excpected callback 
    .require('Table2', 'doBar', 'notFound') 
    .then(doStuff); 

這簡化了一些東西。然而,問題是我需要能夠創建表類,其名稱可以從第一次增加推導到require這導致我上面的問題...

回答

4

爲什麼不簡單地通過構造函數函數轉換爲require方法?這樣你避開了從名稱到功能轉換的整個問題。那麼你的榜樣看起來像:

Db.using(db) //the database object 
    .require(Table1Db, 'doFoo', 'success') //table constructor, function name, expected callback 
    .require(Table2Db, 'doBar', 'notFound') 
    .then(doStuff); 

但是,如果你真的想用一個字符串...

你爲什麼deadset使用eval避免?它是一種語言中的工具,每種工具都有其用途(就像每一種工具都可能被濫用一樣)。如果您擔心允許任意執行,則簡單的正則表達式測試應該可以確保您的使用安全。

如果你死心塌地就避免eval,如果您的所有構造函數在默認的全球範圍內創建(即window對象),這會工作:

function create(name) { 
    return new window[name](); 
} 

如果你想獲得幻想和支持的命名空間對象(即create('MyCompany.MyLibrary.MyObject'),你可以做這樣的事情:

function create(name) { 
    var current, 
     parts, 
     constructorName; 

    parts = name.split('.'); 
    constructorName = parts[parts.length - 1]; 
    current = window; 
    for (var i = 0; i < parts.length - 1; i++) { 
    current = current[parts[i]]; 
    } 

    return new current[constructorName](); 
} 
+1

首先,謝謝你的迴應。像往常一樣,在回顧一個答案後,我覺得有點愚蠢,因爲錯過了一些(回想起來相當明顯)的東西。在這種情況下,字符串更容易,但是通過構造函數(我不知道可以這樣做)看起來更簡潔,更重要的是清晰。我並不是反對使用eval,並且正如你所說的那樣,它有它的位置,但是經驗告訴我,如果我認爲我需要使用它的時候有99%的時間我不懂這門語言。 (這是其中的一次)。 – Yacoby 2010-07-09 22:51:15

+0

@Yacoby說得好! :)尤其是最後的句子。我希望大家都會這樣想。 – galambalazs 2010-07-09 22:53:32

+0

這是一個很好的答案。學習了關於JavaScript的新內容!謝謝:) – rossipedia 2010-07-09 23:32:27

2

你是在完整的門雖然安娜貝爾的解決方案讓我們你做什麼你只是想在你想要的方式。 (通過字符串),讓我爲您提供一個替代方案。 (傳遞函數的引用)

function Foo(){} 
function create(name){ 
    return new name(); 
} 
create(Foo); // IS equivalent to new Foo(); 

而且瞧,它的工作原理 :)我告訴你。你在解決方案的門檻上。

發生了什麼事是你已經嘗試這樣做

new 'Foo'() 

這並不使多大意義,不是嗎?但是現在你通過引用來傳遞函數,所以行return new name();將被轉換爲return new Foo();,就像你期望的那樣。

現在打開門以提取應用程序的異步性。玩的開心!

附錄:函數是第一類對象,這意味着它們可以通過引用存儲,作爲參數傳遞或作爲值由另一個函數返回。

+0

'require()'的第二個和第三個參數仍然必須是字符串,它們標識的對象是還不存在的對象的屬性。 – Annabelle 2010-07-09 22:57:39

+0

是的你是對的。 – galambalazs 2010-07-09 23:32:50