JavaScriptで文字列から関数を作成する方法はありますか?


107

例えば;

var s = "function test(){
  alert(1);
}";

var fnc = aMethod(s);

これが文字列の場合、fncという関数が必要です。そして、fnc();警告画面をポップ。

eval("alert(1);") 私の問題を解決しません。

回答:


73

stringから関数を作成する4つの異なる方法のjsperfテストを追加しました。

  • 関数クラスでのRegExpの使用

    var func = "function (a, b) { return a + b; }".parseFunction();

  • 「return」でFunctionクラスを使用する

    var func = new Function("return " + "function (a, b) { return a + b; }")();

  • 公式の関数コンストラクターを使用する

    var func = new Function("a", "b", "return a + b;");

  • 評価の使用

    eval("var func = function (a, b) { return a + b; };");

http://jsben.ch/D2xTG

2つの結果サンプル: ここに画像の説明を入力してください ここに画像の説明を入力してください


@KthProgチルダウン;)。この状況のように、必ずしも悪いわけではありません。jsperfは現在ダウンしています。幸いにも、Bulkからコメントを受け取ったとき、ダウンする前に結果のスクリーンショットを追加しました。
プナ2016年

@KthProg FYIこれはモデレートシステムによって生成された返信定型文でした。:)キューにポップアップ表示され、所定の問題をチェックします。このコメントの1つは修正するように設計されています。これは厳格な規則ではありません。コメントはコマンドではなく提案の形式になっています。
Dan Smith

174

文字列から関数を作成するより良い方法は、以下を使用することFunctionです:

var fn = Function("alert('hello there')");
fn();

これには、現在のスコープ内の変数(グローバルでない場合)が新しく作成された関数に適用されないという利点と欠点があります。

引数を渡すことも可能です:

var addition = Function("a", "b", "return a + b;");
alert(addition(5, 3)); // shows '8'

5
で、同意Functionローカルスコープを汚染していないと、なぜこれがevalエンジンのために懸命に最適化を行いOPの例では...、私は希望:var fnc = Function('return '+s)();
CMS

これはおそらく受け入れられる答えだと思います。eval()よりもはるかに安全です。
ブライアンレイナー、2015

私の友人であるあなたは、多くの賛成に値します。これには、イベントなどに割り当てることができる関数オブジェクトを作成できるという利点があります。例:element.onclick = Function( "alert( 'test');");
Ryan Griggs 2016年

1
@RyanGriggsあなたの場合、「評価」機能は必要ないので、のように書くのがよいでしょうelement.onclick = function() { alert("test"); }
Lekensteyn 2016年

1
あなたは私の例から正しいです。ただし、文字列に格納されている任意の関数を割り当てたい場合は、この方法が最適です。これは私が実際にやろうとしていることです。文字列変数に保存されている複数の関数があり、1つをonclickアクションに割り当てたいです。
ライアングリッグス2016年

38

あなたはかなり近いです。

//Create string representation of function
var s = "function test(){  alert(1); }";

//"Register" the function
eval(s);

//Call the function
test();

ここだ作業フィドルが


関数が宣言されていることは知っていましたが、関数名を呼び出すことができませんでした。どうもありがとう。
ymutlu、2011年

4
eval今後の検索者への必須の警告:evalハッカーの抜け穴を開くことができます:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…しかし、その危険性を知っていて回避できる場合、これは簡単な方法です文字列から関数を作成

関数の名前がデータベースレコードから取得されたものではない場合はどうなりますか?
Marcel Djaman

13

はい、使用することFunctionは素晴らしいソリューションですが、少し先に進んで、文字列を解析して実際のJavaScript関数に変換するユニバーサルパーサーを準備できます...

if (typeof String.prototype.parseFunction != 'function') {
    String.prototype.parseFunction = function () {
        var funcReg = /function *\(([^()]*)\)[ \n\t]*{(.*)}/gmi;
        var match = funcReg.exec(this.replace(/\n/g, ' '));

        if(match) {
            return new Function(match[1].split(','), match[2]);
        }

        return null;
    };
}

使用例:

var func = 'function (a, b) { return a + b; }'.parseFunction();
alert(func(3,4));

func = 'function (a, b) { alert("Hello from function initiated from string!"); }'.parseFunction();
func();

ここにjsfiddleがあります


こんにちは、このメソッドへの矢印関数のサポートをサポートしてください。
sathish kumar

1
typescirptでこのエラーを受け取ります。「プロパティ 'parseFunction'はタイプ 'String'に存在しません。」
Cegone

11

の動的関数名 JavaScript

使用する Function

var name = "foo";
// Implement it
var func = new Function("return function " + name + "(){ alert('hi there!'); };")();
// Test it
func();
// Next is TRUE
func.name === 'foo'

ソース:http : //marcosc.com/2012/03/dynamic-function-names-in-javascript/

使用する eval

var name = "foo";
// Implement it
eval("function " + name + "() { alert('Foo'); };");
// Test it
foo();
// Next is TRUE
foo.name === 'foo'

使用する sjsClass

https://github.com/reduardo7/sjsClass

Class.extend('newClassName', {
    __constructor: function() {
        // ...
    }
});

var x = new newClassName();
// Next is TRUE
newClassName.name === 'newClassName'

6

この手法は、最終的にはevalメソッドと同等である可能性がありますが、一部の人にとっては有用である可能性があるため、追加したかったのです。

var newCode = document.createElement("script");

newCode.text = "function newFun( a, b ) { return a + b; }";

document.body.appendChild( newCode );

これは、この<script>要素をドキュメントの最後に追加するのと機能的に似ています。例:

...

<script type="text/javascript">
function newFun( a, b ) { return a + b; }
</script>

</body>
</html>


1

動的引数の例:

let args = {a:1, b:2}
  , fnString = 'return a + b;';

let fn = Function.apply(Function, Object.keys(args).concat(fnString));

let result = fn.apply(fn, Object.keys(args).map(key=>args[key]))

ありがとう。非常に興味深い
ДмитрийВасильев
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.