0

eval() について多くの異なる意見を聞いたことがありますが、このコンテキストで eval() を使用してもよいかどうか少し確信が持てません:

次のようなオブジェクトがあるとします。

var bla = {
blubb: function (callback) {
       //GET some stuff via ajax
       //call the callback
    }
}

そして、次のような文字列:

 var someString = "bla.blubb";

関数 (およびコールバック) を呼び出すために文字列を評価するのは悪いことですか?

var callMe = eval(someString)
callMe(function(){
   alert('yay')!
});
4

4 に答える 4

5

私は eval() について多くの異なる意見を聞いたことがあります

eval一般的に悪ではなく、用途があります。

このコンテキストで eval() を使用してもよいかどうか不明

いいえ、これは問題ありません。単純なブラケット表記メンバー operatorを使用した、はるかに優れたソリューションがあります。これは SO で毎日尋ねられるので、ここに何百もの重複をリストすることができます (最初のいくつかの Google 検索結果のみ):

于 2013-01-18T10:34:40.897 に答える
1

あなたのデザイン全体が完全に悪いわけではないとしましょう (しかし少しだけ)。

これは、 にあるものを制限して指定することを意味しますsomeString。たとえば、オブジェクトへのパスとその関数を、引数なしで呼び出して (危険性を大幅に軽減します)、グローバル オブジェクトのコンテキストで呼び出すことができます。

次に、文字列を解析して関数を呼び出すのは簡単evalです。これはより安全です。例えば ​​:

window.a = {b:{c:function(){console.log('here')}}};
var someString = "a.b.c";

var path = someString.split('.');
var f = window;
for (var i=0; i<path.length; i++) f = f[path[i]];
f.call(null);

改善は、ルート オブジェクト (ウィンドウではなく) を修正して、あらゆる種類の呼び出しを回避することです。

于 2013-01-18T10:21:07.627 に答える
0

デバッグが難しいので、これもまた悪です。より良いアプローチは、次のようなものを使用することです。

function getValue(namespace, parent) {
    var parts = namespace.split('.'),
        current = parent || window;
    for (var i = 0; i < parts.length; i += 1) {
        if (current[parts[i]]) {
            current = current[parts[i]];
        } else {
          if (i >= parts.length - 1)
            return undefined;
        }
    }
    return current;
}
var foo = {
    bar: {
        baz: function () { alert('baz'); }
    }
};
var f = getValue('foo.bar.baz'); //true
if (typeof f === 'function') {
    f();
}

コードは 1 つではありeval('foo.bar.baz')ませんが、実際に何が起こっているのかを把握し、ブレーク ポイントを使用してデバッグすることもできます。

ここでパフォーマンスについて話す場合、いくつかの jsperf の例を示します。

  1. http://jsperf.com/eval-vs-loop
  2. http://jsperf.com/eval-vs-loop/2
于 2013-01-18T10:20:58.727 に答える
0

オブジェクトがどのように見えるかがわかっている場合は、javascript で「安全な評価」を使用できることを忘れないでください。

スコープ内:

this.foo = { bar:function(){return "baz"}};

// some code.
var obj = "foo";
var param = "bar";

this[obj][param](); // same as this.foo.bar();

特定のもの (たとえば、テンプレート化など) を扱っていない限り、オブジェクトを呼び出すために eval を使用する必要はありません。

于 2013-01-18T10:28:13.483 に答える