1

のような"AppNamespace.SomeObject.ClassName"文字列があり、文字列が実際のコンストラクター関数を表していることがわかっている場合、それをステートメントで使用するための最良/推奨の方法はvar foo = new AppNamespace.SomeObject.ClassName何ですか?

私はそれをできた:

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 つの解決策に基づいて、それぞれの長所と短所は何ですか?

4

2 に答える 2

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));
于 2012-04-07T01:49:23.123 に答える
2

あなたはできる...

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

jsFiddle .

古いブラウザでは、 shim でき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));
};
于 2012-04-07T01:53:41.233 に答える