2012-04-07 23 views
1

如果我有一個像"AppNamespace.SomeObject.ClassName"這樣的sting,並且我知道字符串表示和實際的構造函數,那麼使用它的最佳/推薦方法是什麼在像var foo = new AppNamespace.SomeObject.ClassName這樣的聲明中?在JavaScript中獲取名稱空間,字符串表示的構造函數的最佳方法

我可以這樣做:

var s = "AppNamespace.SomeObject.ClassName" 
var foo = new (eval(s)) 

或喜歡的東西:

var parts = "AppNamespace.SomeObject.ClassName".split(".") 
var foo = new (window[parts[0]][parts[1]][parts[2]]) 

,但我不知道是否有更好的解決方案,不涉及eval或具有分割字符串和循環通過它的部分。有沒有人有任何想法?如果沒有,基於我提出的兩種解決方案,每種解決方案的優缺點是什麼?

回答

2

你可以這樣做......

var obj = new ('AppNamespace.SomeObject.ClassName' 
       .split('.') 
       .reduce(function(object, key) { 
          return object[key]; 
         }, window)); 

jsFiddle

在較舊的瀏覽器上,您可以填充reduce()

此代碼按照句點(.)分割字符串,然後從左到右迭代每個字符串,以window作爲起始對象(如果不是,則更改它)並獲取每個子屬性,直到它到達最右邊(在你的例子中爲ClassName)。

new (...)實例化此對象。

你可以把它寫成一個可重複使用的功能...

var getObjectByString = function(string, baseObject, delimiter) { 
    // Only checks for string primitives, but that's OK for this example. 
    if (typeof string !== 'string') { 
     throw new TypeError('First argument is required and must be a string.'); 
    } 

    baseObject = baseObject || window; 
    delimiter = delimiter || '.'; 

    return string 
      .split(delimiter) 
      .reduce(function(object, key) { 
         return object[key]; 
        }, baseObject)); 
}; 
+0

Array#reduce在當前瀏覽器環境中的可用性有限:https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/Reduce – dfreeman 2012-04-07 01:55:05

+0

@dfreeman是的,但它可以在任何瀏覽器中輕鬆地擦除。 – alex 2012-04-07 02:07:36

+0

對於它的價值,我在我的應用中使用了underscore.js – 2012-04-07 02:10:47

3

eval是邪惡的。使用循環選項。

關於循環選項的好處是對象是通過引用傳遞的。所以:

function getObjectFromString(str) { 
    var parts = str.split("."), curr = window, last = parts.pop(), p; 
    while(p = parts.shift()) curr = curr[p]; 
    return curr[last]; 
} 

該函數返回目標對象,在你的例子中是你正在尋找的構造函數。

var s = "AppNamespace.SomeObject.ClassName"; 
var foo = new (getObjectFromString(s)); 
+0

有很好的理由的eval是邪惡的,但轉換爲字符串,我知道是安全的對象肯定是不是其中之一,對? – 2012-04-07 02:06:46

相關問題