JavaScriptで動的に名前が付けられたメソッドを呼び出すにはどうすればよいですか?


113

私は、Webページが構築されるときにWebページに挿入されるJavaScriptを動的に作成する作業をしています。

JavaScriptはlistbox、別のでの選択に基づいてにデータを入力するために使用されlistboxます。いずれかの選択listboxが変更されると、選択されたの値に基づいてメソッド名が呼び出されますlistbox

例えば:

Listbox1 含む:

  • Colours
  • Shapes

Coloursが選択されている場合、populate_Colours別のを生成するメソッドを呼び出しますlistbox

私の質問を明確にするために:populate_ColoursJavaScriptでその呼び出しを行うにはどうすればよいですか?


これに対しては、ローカルのブランチを1つの「populate」メソッドに含めることをお勧めします。これにより、テストが容易になり、「ハック」が少なくなります
アーロンパウエル、

ここで私の答えを見てください。JavaScriptで名前を指定して呼び出す
Hugo R

回答:


208

populate_Coloursメソッドがグローバル名前空間にあると仮定すると、次のコードを使用できます。これは、オブジェクトが連想配列であるかのようにすべてのオブジェクトプロパティにアクセスできること、およびすべてのグローバルオブジェクトが実際にはwindowホストオブジェクトのプロパティであることの両方を利用します。

var method_name = "Colours";
var method_prefix = "populate_";

// Call function:
window[method_prefix + method_name](arg1, arg2);

9
ご返信ありがとうございます。「ウィンドウ」ビットは、ググってグローバルオブジェクトがウィンドウオブジェクトの一部であることがわかるまで、本当に私を驚かせました。今では理にかなっています!ありがとうございました。参考
Chris B

3
対象とした関数がjQuery "fn"名前空間にあることを除いて、私は同様のことを行いました。例$.fn[method_prefix + method_name](arg1, arg2);
codecraig

1
いいね。try/ catchブロックを追加する価値があるでしょう。
LeeGee、2014

これは明らかな場合もありますが、機能しない場合は、関数$(function () {window.loadコードの外側に関数をスローしてください:)
Stan Smulders

1
@peterこれは、角括弧がこのコンテキストではプロパティアクセサーではないため、配列を表すためです。配列は関数ではないため、呼び出すことはできません。
user4642212

39

Triptychが指摘しているように、ホストオブジェクトのコンテンツでグローバルスコープ関数を見つけて呼び出すことができます。

グローバル名前空間の汚染を大幅に減らすよりクリーンな方法は、次のように関数を直接配列に明示的に置くことです。

var dyn_functions = [];
dyn_functions['populate_Colours'] = function (arg1, arg2) { 
                // function body
           };
dyn_functions['populate_Shapes'] = function (arg1, arg2) { 
                // function body
           };
// calling one of the functions
var result = dyn_functions['populate_Shapes'](1, 2);
// this works as well due to the similarity between arrays and objects
var result2 = dyn_functions.populate_Shapes(1, 2);

この配列は、グローバルホストオブジェクト以外のオブジェクトのプロパティにもなり得ます。つまり、jQueryなどの多くのJSライブラリと同じように、独自の名前空間を効果的に作成できます。これは、同じページに複数の個別のユーティリティライブラリを含める場合に、競合を減らすのに役立ち、(デザインの他の部分で許可されている場合)コードを他のページで簡単に再利用できます。

次のようなオブジェクトを使用することもできます。

var dyn_functions = {};
dyn_functions.populate_Colours = function (arg1, arg2) { 
                // function body
           };
dyn_functions['populate_Shapes'] = function (arg1, arg2) { 
                // function body
           };
// calling one of the functions
var result = dyn_functions.populate_Shapes(1, 2);
// this works as well due to the similarity between arrays and objects
var result2 = dyn_functions['populate_Shapes'](1, 2);

配列またはオブジェクトのいずれかを使用すると、関数の設定またはアクセスのいずれかの方法を使用でき、もちろん他のオブジェクトもそこに格納できます。次のようにJSリテラル表記を使用することで、動的でないコンテンツのどちらかのメソッドの構文をさらに減らすことができます。

var dyn_functions = {
           populate_Colours:function (arg1, arg2) { 
                // function body
           };
         , populate_Shapes:function (arg1, arg2) { 
                // function body
           };
};

編集:もちろん、より大きな機能ブロックの場合は、コード機能を体系的にカプセル化する一般的な方法である非常に一般的な「モジュールパターン」に上記を拡張できます。


それはそれをきれいに保つ良い方法です。どのように私はメソッドを呼び出すでしょうか?window [dyn_functions ['populate_Colours'](arg1、arg2)は機能しますか?
クリスB

私自身の質問への回答-window [dyn_functions ['populate_Colours'](arg1、arg2)];をテストしました。そしてそれは確かに機能します。
クリスB

4
epascarelloが指摘するように、通常は「ウィンドウ」-「dyn_functions ['populate_Colours'](arg1、arg2);」は必要ありません。動作します。実際、Webブラウザ以外のJS環境で使用される可能性のあるルーチンを記述している場合、グローバルオブジェクトの名前を含めないことで、コードの移植性が向上します。ただし、これには例外があります。関数にdyn_functionsと呼ばれるローカル変数がある場合は、より具体的に参照する必要がありますが、この状況は(賢明な命名規則を使用することにより)とにかく回避するのが最善です。
デビッドスピレット2009年

1
この投稿は'09からのものなので、おそらくこれまでにこれを知っていますが、配列を作成し、配列のプロパティ(インデックスではない)に割り当てています。あなたにも行う可能性がありますvar dyn_functions = {};あなたは不配列を作成しないように...とはいえ、これは大きな問題ではありません。
David Sherret、2013年

過度に複雑な答えですが、機能します。一連のパターン化された関数があり、実行を選択するために決定木が必要なシナリオでは、リソースの負荷がかかると思います。この方法は、タスクを実行するのが非常に複雑になる可能性があります。とはいえ、自分のクラスオブジェクトを関連付けている場合、これはオブジェクト自体を定義するための推奨アプローチです。
GoldBishop 2017年

30

この目的で/ / を使用しないことをお勧めします。 代わりに、次のようにします。 globalwindoweval

すべてのメソッドをハンドラーのプロパティとして定義します。

var Handler={};

Handler.application_run = function (name) {
console.log(name)
}

このように呼んでください

var somefunc = "application_run";
Handler[somefunc]('jerry');

出力:ジェリー


17

あなたはこのようにそれを行うことができます:

function MyClass() {
    this.abc = function() {
        alert("abc");
    }
}

var myObject = new MyClass();
myObject["abc"]();

5

ServiceWorkerまたはWorker、交換するwindowself

self[method_prefix + method_name](arg1, arg2);

ワーカーはDOMにアクセスできないためwindow、無効な参照です。この目的で同等のグローバルスコープ識別子はselfです。


2

他の回答が示唆するように、ウィンドウを使用することはお勧めしません。thisそれに応じて使用およびスコープを設定します。

this['yourDynamicFcnName'](arguments);

別のきちんとしたトリックは、異なるスコープ内で呼び出し、それを継承に使用することです。関数をネストしていて、グローバルウィンドウオブジェクトにアクセスしたいとします。あなたはこれを行うことができます:

this['yourDynamicFcnName'].call(window, arguments);

1

こんにちはこれを試してください、

 var callback_function = new Function(functionName);
 callback_function();

パラメータ自体を処理します。


キャッチされていない参照エラー
-functionNameが

@brianlmerrittあなたはfunctionName... の値を定義する必要があります回答者はあなたがすでにそれを定義していると仮定しました。
GoldBishop 2017年

new Function()をこの目的でそのように使用することはできないようです。
JCH77

-1

ここでの作業とチェックするための簡単な解決策である機能の存在をし、動的にその機能をトリアージ別の関数では、

トリガー機能

function runDynmicFunction(functionname){ 

    if (typeof window[functionname] == "function"  ) { //check availability

        window[functionname]("this is from the function it "); //run function and pass a parameter to it
    }
}

そして、あなたはおそらくこのようにphpを使って動的に関数を生成することができます

function runThis_func(my_Parameter){

    alert(my_Parameter +" triggerd");
}

これで、動的に生成されたイベントを使用して関数を呼び出すことができます

<?php

$name_frm_somware ="runThis_func";

echo "<input type='button' value='Button' onclick='runDynmicFunction(\"".$name_frm_somware."\");'>";

?>

必要な正確なHTMLコードは

<input type="button" value="Button" onclick="runDynmicFunction('runThis_func');">

-3

これで試してください:

var fn_name = "Colours",
fn = eval("populate_"+fn_name);
fn(args1,argsN);

このパターンを使用する意味は何ですか?私は、eval関数がその使用に関連するいくつかの奇妙な副作用を持っていることを読みました。それが最後の手段でない限り、私は一般にそれを避けようとします。
GoldBishop 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.