2011-07-06 10 views
3

珍しいケースを除き、JavaScriptのeval() is considered bad practiceJavaScript、Eval、New - 貧しい人の工場

文字列を受け取り、その型名でオブジェクトを作成するコードの断片に遭遇しました。 (より速く、より安全、クリーン、および/または)evalを使用せずに、クラス作成を達成するための方法を

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

が良くはあります。エラーチェック、ビジネスロジック、およびコンテキストので削除行うため、ここでは次のようになります。

私はその名前によってクラスを作成するための汎用的な方法を探しています。

例えば、コードの別の部分がJavaScriptファイルを動的にロードしたり、コードを生成したり、ユーザーの拡張を許可するとしたら、そのコードの他の部分は、存在。

+0

エラーチェック、ら。 al。は、StackOverflowの簡潔な例を作るために削除されました。 –

+0

なぜそれの背後にあるのかをあまり気にせずに、klassは文字列です。矛盾は、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

私は本当にこれに分割クレジットを与えたいと思います。デビッド・ティタレンコ氏は、自分のコメントで、私がevalなしでやろうとしていたことをすることはできないと述べました。 Alexei Levenkovは、私が必要としていた文字列を取り、ファクトリオブジェクトからクラスを返す次の最も近いものを提供しました。だから私はこれをeval()を使わないで回避するための最良の方法としてこれを受け入れています。あなた方全員に感謝します。 –

1

evalは必要ありません。名前の代わりにオブジェクトを単に渡すことができ、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

エラーチェックが重要なので、削除しないでください。我々はガビの「ハード工場」ソリューション@で行くと言う:eval()呼び出しは、この場合にも、正当である

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() 

:今

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 

は、元の「ソフト工場」ソリューションを見てみましょう。すべての言語構成(yes、even eval())が理由のために有用であり、言語の一部であることを理解することは重要です。いくつかの人々が間違った状況でそれを過度に使う、またはそれを使用するという事実は、それが正しいものでは非常に強力なツールではないということを意味しません。

+0

また、 'eval'は入力に注意する必要があることを明確にすべきです:' klass'が 'function(){};/*あなたの邪悪なコード* /(function(){}) '、あなたは何か問題を抱えている –

+0

それでは、私が同意するが、evalに関する質問の一部ではないエラーチェックは、これはevalを使用するためのいくつかの許容可能なケースの1つであり、これがこの機能を実現するための適切な方法ですか? –

+0

関数に文字列を渡し、文字列のオブジェクト表現を取得する方法があるかどうかを確認するには、評価なしでこれを行う方法がありません。 –

関連する問題