web-dev-qa-db-ja.com

文字列をJavaScriptの関数呼び出しに変換する方法

私は次のような文字列を得ました:

settings.functionName + '(' + t.parentNode.id + ')';

私はそのように関数呼び出しに変換したいのですが。

clickedOnItem(IdofParent);

もちろんこれはJavaScriptで行う必要があります。私がsettings.functionName + '(' + t.parentNode.id + ')';に対してアラートを出したとき、それはすべてを正しくしているようです。それが変換される関数を呼び出すだけです。

伝説:

settings.functionName = clickedOnItem

t.parentNode.id = IdofParent
253

私はevalが嫌いなので見て、私は 一人じゃない

var fn = window[settings.functionName];
if(typeof fn === 'function') {
    fn(t.parentNode.id);
}

編集:@ Mahanのコメントに答えて:この場合、settings.functionName"clickedOnItem"になります。これにより、実行時にvar fn = window[settings.functionName];var fn = window["clickedOnItem"]に変換され、function clickedOnItem (nodeId) {}への参照が取得されます。変数内の関数への参照を取得したら、「変数を呼び出す」ことでこの関数を呼び出すことができます。つまり、fn(t.parentNode.id)clickedOnItem(t.parentNode.id)と等しく、OPが望んでいたものです。

より完全な例:

/* Somewhere: */
window.settings = {
  /* [..] Other settings */
  functionName: 'clickedOnItem'
  /* , [..] More settings */
};

/* Later */
function clickedOnItem (nodeId) {
  /* Some cool event handling code here */
}

/* Even later */
var fn = window[settings.functionName]; 
/* note that settings.functionName could also be written
   as window.settings.functionName. In this case, we use the fact that window
   is the implied scope of global variables. */
if(typeof fn === 'function') {
    fn(t.parentNode.id);
}
354
window[settings.functionName](t.parentNode.id);

Eval()は必要ありません

70
Fabien Ménager

スコープをサポートしながら、これを行うためのより一般的な方法は次のとおりです。

// Get function from string, with or without scopes (by Nicolas Gauthier)
window.getFunctionFromString = function(string)
{
    var scope = window;
    var scopeSplit = string.split('.');
    for (i = 0; i < scopeSplit.length - 1; i++)
    {
        scope = scope[scopeSplit[i]];

        if (scope == undefined) return;
    }

    return scope[scopeSplit[scopeSplit.length - 1]];
}

それが何人かの人々を助けることを願っています。

66
NGauthier

JavaScriptには、文字列を評価してコードとして実行する eval 関数があります。

eval(settings.functionName + '(' + t.parentNode.id + ')');
14
Andrew Hare

eval()はそのために必要な関数ですが、evalの使用を最小限に抑えるためにこれらのうちの1つを試すことをお勧めします。うまくいけば、それらのうちの1つがあなたにとって理にかなっているでしょう。

機能を保存する

関数を文字列としてではなく関数として格納し、後で関数として使用します。あなたが実際に関数を保存する場所はあなた次第です。

var funcForLater = clickedOnItem;

// later is now
funcForLater(t.parentNode.id);

または

someObject.funcForLater = clickedOnItem;    
// later is now    
(someObject.funcForLater)(t.parentNode.id);

ストア機能名

関数名を文字列として格納する必要がある場合でも、次のようにすると複雑さを最小限に抑えることができます。

(eval(settings.functionName))(t.parentNode.id);

これにより、作成して評価する必要があるJavascriptの量が最小限に抑えられます。

ハンドラの辞書

あなたが必要とするかもしれない全てのアクション関数をオブジェクトの中に入れ、そしてそれらを文字列を使って辞書形式で呼び出す。

// global
itemActions = { click: clickedOnItem, rightClick: rightClickedOnItem /* etc */ };

// Later...
var actionName = "click"; // Or wherever you got the action name
var actionToDo = itemActions[actionName];
actionToDo(t.parentNode.id);

(注意:代わりにここでitemActions[actionName](t.parentNode.id);という構文を使用した場合、関数はitemActionsのメソッドとして呼び出されます。)

13
Jesse Millikan

私は最初の答えが好きで、evalが嫌いですが、他の方法(evalに似た方法)があることを付け加えたいと思います。しかし、場合によっては、ajaxの呼び出しの前後にjavascriptコードを呼び出したいことがあります。このコードをajaxではなくカスタム属性に含めると、次のように使用できます。

    var executeBefore = $(el).attr("data-execute-before-ajax");
    if (executeBefore != "") {
        var fn = new Function(executeBefore);
        fn();
    }

あるいは、複数回呼び出す必要がある場合は、これを関数キャッシュに保存します。

繰り返しますが、他の方法がある場合は、evalやこの方法を使用しないでください。

9
nsimeonov

settings.functionNameがすでに関数の場合は、これを実行できます。

settings.functionName(t.parentNode.id);

そうでなければ、これはsettings.functionNameが単なる関数の名前である場合にも機能するはずです。

if (typeof window[settings.functionName] == "function") {
    window[settings.functionName](t.parentNode.id);
}
8
Gumbo

私は、文字列として関数名を取り、それを呼び出し、そして関数に引数を渡すことができることを望みました。この質問に対する選択された答えを得ることができませんでしたが、これ answer で正確に説明されています。ここに短いデモがあります。

function test_function(argument)    {
    alert('This function ' + argument); 
}

functionName = 'test_function';

window[functionName]('works!');

これは複数の引数に対しても機能します。

7
B Rad C

従来のwindow['someFunctionName']()は最初はうまく機能しなかったので、これには少し時間がかかりました。私の関数の名前はデータベースからのAJAXレスポンスとして引き出されていました。また、何らかの理由で、私の関数はウィンドウの範囲外で宣言されていたので、これを修正するためには、呼び出し元の関数を書き直す必要がありました

function someFunctionName() {}

window.someFunctionName = function() {}

そこから、私はwindow['someFunctionName']()を簡単に呼び出すことができます。これが誰かに役立つことを願っています!

3
illusivefingers

Nicolas Gauthierの答えに基づく:

var strng = 'someobj.someCallback';
var data = 'someData';

var func = window;
var funcSplit = strng.split('.');
for(i = 0;i < funcSplit.length;i++){
   //We maybe can check typeof and break the bucle if typeof != function
   func = func[funcSplit[i]];
}
func(data);

私はこのようなものを使うのが好きです。

window.callbackClass['newFunctionName'] = function(data) { console.log(data) };
...
window.callbackClass['newFunctionName'](data);
2
Tom Johnson

例えばnode.jsのように、CommonJS仕様を使用するJavaScriptでは、以下に示すものを実行できます。 windowオブジェクトで定義されていなくても、文字列で変数にアクセスするのにかなり便利です。 MyClass.jsという名前のCommonJSモジュール内に定義されたMyClassという名前のクラスがある場合

// MyClass.js
var MyClass = function() {
    // I do stuff in here. Probably return an object
    return {
       foo: "bar"
    }
}

module.exports = MyClass;

これで、MyOtherFile.jsという別のファイルからこの素敵な魔術を実行できます。

// MyOtherFile.js

var myString = "MyClass";

var MyClass = require('./' + myString);
var obj = new MyClass();

console.log(obj.foo); // returns "bar"

CommonJSがこのような喜びであるもう1つの理由。

0
nackjicholson