如何在Javascript中调用动态命名方法?


113

我正在动态创建一些JavaScript,这些JavaScript将在构建时插入到网页中。

JavaScript将listbox根据另一个中的选择来填充一个listboxlistbox更改一个选项时,它将基于的选定值调用方法名称listbox

例如:

Listbox1 包含:

  • Colours
  • Shapes

如果Colours选择,它将调用populate_Colours填充另一个方法listbox

为了澄清我的问题:如何populate_Colours使用JavaScript 进行调用?


我反对这样做,建议在单个“填充”方法中设置本地分支。这将使其更具可测试性,并且看起来不那么“ hacky”
Aaron Powell 2009年

在这里查看我的答案。在javascript中按名称调用
Hugo R

Answers:


208

假定该populate_Colours方法位于全局名称空间中,则可以使用以下代码,该代码利用以下两种方式:可以访问所有对象属性(就像该对象是关联数组一样),并且所有全局对象实际上都是window宿主对象的属性。

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

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

9
感谢您的回复。直到我用谷歌搜索“窗口”时,才发现它确实是窗口对象的一部分。现在有道理了!谢谢。仅供参考,我在这里找到了关于它的好页面 devlicio.us/blogs/sergio_pereira/archive/2009/02/09/…–
克里斯·

3
除了目标功能在jQuery“ fn”命名空间中外,我执行了类似的操作。例如,$.fn[method_prefix + method_name](arg1, arg2);
codecraig 2011年

1
真好 值得添加一个try/ catch块。
LeeGee 2014年

这可能是明显一些,但对于那些无法得到它的工作:扔你的功能外$(function () {,并window.load代码:)
斯坦Smulders

1
@peter因为在此上下文中方括号不是属性访问器,而是表示数组。数组不是函数,因此无法调用它们。
user4642212 '18

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

该数组也可以是全局宿主对象以外的某些对象的属性,这意味着您可以像许多JS库(如jQuery)一样有效地创建自己的名称空间。如果/当您在同一页面中包含多个单独的实用程序库时,这对于减少冲突很有用,并且(在设计的其他部分允许的情况下)可以使重用其他页面中的代码更加容易。

您还可以使用这样的对象,您可能会发现它更干净:

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);” 将工作。实际上,如果您编写的程序可能会在除We​​b浏览器之外的JS环境中使用,则不包括全局对象名称的名称将使代码更易于移植。但是,有一个例外:如果函数中有一个名为dyn_functions的局部变量,则您需要更具体地指代它,但是无论如何(最好通过使用明智的命名约定)最好避免这种情况。
David Spillett

1
由于这篇文章来自'09,您可能现在就知道了,但是您正在创建一个数组,然后分配给该数组的属性(而不是索引)。您也可以这样做,var dyn_functions = {};这样就不必不必要地创建数组了……但这不是一个大问题。
David Sherret

答案过于复杂,但确实有效。我认为在具有一系列模式函数并且需要决策树来选择执行的情况下,资源负担很大,这种方法执行任务可能过于复杂。但是,如果我要连接自己的类对象,则这将是定义对象本身的首选方法。
GoldBishop's

30

我建议不要为此使用global/ window/ eval
相反,请按照以下方式进行操作:

将所有方法定义为Handler的属性:

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

@brianlmerritt,您必须为functionName... 定义值。答案者假设您已经定义了该值。
GoldBishop

似乎不能为此目的使用new Function()。
JCH77 '19

-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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.