如何在 Javascript 中调用动态命名的方法?
Posted
技术标签:
【中文标题】如何在 Javascript 中调用动态命名的方法?【英文标题】:How do I call a dynamically-named method in Javascript? 【发布时间】:2010-11-01 11:14:57 【问题描述】:我正在动态创建一些 javascript,这些 JavaScript 在构建时将插入到网页中。
JavaScript 将用于根据另一个listbox
中的选择填充listbox
。当一个listbox
的选择发生变化时,它将根据listbox
的选定值调用方法名称。
例如:
Listbox1
包含:
Colours
Shapes
如果选择了Colours
,那么它将调用填充另一个listbox
的populate_Colours
方法。
澄清我的问题:如何在 JavaScript 中进行 populate_Colours
调用?
【问题讨论】:
我建议不要这样做,而是在单一的“填充”方法中建立本地分支机构。它会让它更可测试,看起来不那么“hacky” 在这里查看我的答案。 call by name in javascript 【参考方案1】:假设populate_Colours
方法在全局命名空间中,您可以使用以下代码,该代码利用了所有对象属性都可以像访问关联数组一样被访问,并且所有全局对象实际上都是window
主机对象。
var method_name = "Colours";
var method_prefix = "populate_";
// Call function:
window[method_prefix + method_name](arg1, arg2);
【讨论】:
感谢您的回复。 '窗口'位真的让我震惊,直到我用谷歌搜索它并发现全局对象是窗口对象的一部分。现在它是有道理的!谢谢你。仅供参考,我在这里找到了一个很好的页面devlicio.us/blogs/sergio_pereira/archive/2009/02/09/… 我做了类似的事情,除了我的目标函数在 jQuery“fn”命名空间中。例如,$.fn[method_prefix + method_name](arg1, arg2);
不错。也许值得添加一个try
/catch
块。
这对某些人来说可能很明显,但对于那些无法使其工作的人:将函数扔到您的 $(function ()
和 window.load
代码之外:)
@peter 因为方括号在此上下文中不是属性访问器,而是表示一个数组。数组不是函数,所以你不能调用它们。【参考方案2】:
正如 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) 会工作吗? 回答我自己的问题 - 我刚刚测试了 window[dyn_functions['populate_Colours'](arg1,arg2)];它确实有效。 正如 epascarello 指出的那样,您通常不需要“窗口”-“dyn_functions['populate_Colours'](arg1,arg2);”将工作。事实上,如果您编写的例程可能曾经在 Web 浏览器以外的 JS 环境中使用,那么不包括全局对象的名称将使代码更具可移植性。但是有一个例外:如果您在函数中有一个名为 dyn_functions 的局部变量,那么您需要更具体地指代您所指的内容,但无论如何最好避免这种情况(通过合理的命名约定)。跨度> 因为这篇文章是从 09 年开始的,您现在可能已经知道了,但是您正在创建一个数组,然后分配给数组的属性(而不是索引)。您不妨这样做var dyn_functions = ;
,这样您就不必不必要地创建一个数组......不过这不是一个大问题。
答案过于复杂但确实有效。我认为对于我有一系列模式化函数并且我需要一个决策树来选择执行的场景的资源负载,这种方法执行任务可能过于复杂。不过,如果我要连接自己的类对象,这将是定义对象本身的首选方法。【参考方案3】:
我建议不为此目的使用global
/ window
/ eval
。
相反,这样做:
将所有方法定义为Handler的属性:
var Handler=;
Handler.application_run = function (name)
console.log(name)
现在这样称呼它
var somefunc = "application_run";
Handler[somefunc]('jerry');
输出:杰瑞
从不同文件导入函数时的情况
import func1, func2 from "../utility";
const Handler=
func1,
func2
;
Handler["func1"]("sic mundus");
Handler["func2"]("creatus est");
【讨论】:
为什么不使用global
/ window
/ eval
?【参考方案4】:
你可以这样做:
function MyClass()
this.abc = function()
alert("abc");
var myObject = new MyClass();
myObject["abc"]();
【讨论】:
【参考方案5】:在ServiceWorker
或Worker
中,将window
替换为self
:
self[method_prefix + method_name](arg1, arg2);
Worker 无权访问 DOM,因此 window
是无效引用。用于此目的的等效全局范围标识符是 self
。
【讨论】:
【参考方案6】:我不建议像其他一些答案所建议的那样使用窗口。使用this
和相应的范围。
this['yourDynamicFcnName'](arguments);
另一个巧妙的技巧是在不同的范围内调用并将其用于继承。假设您已经嵌套了该函数并希望访问全局窗口对象。你可以这样做:
this['yourDynamicFcnName'].call(window, arguments);
【讨论】:
我该怎么做打字稿?我在类中有一个方法,它将迭代具有函数名和函数参数的对象数组。被调用的函数存在于同一个类中。但是我收到错误,因为 this[functionName](funcArgument) 不是函数 你能分享一个codepen的例子吗?对于类,请务必考虑词法范围。【参考方案7】:你好,试试这个,
var callback_function = new Function(functionName);
callback_function();
它将自己处理参数。
【讨论】:
未捕获的引用错误 - 未定义函数名 @brianlmerritt 您必须定义functionName
的值...回答者假设您已经定义了该值。
似乎 new Function() 不能像那样用于此目的。【参考方案8】:
去做吧
class User
getName()
return "dilo";
let user =new User();
let dynamicMethod='getName';
console.log(user[dynamicMethod]()); //dilo
【讨论】:
【参考方案9】:用参数动态调用函数的简单函数:
this.callFunction = this.call_function = function(name)
var args = Array.prototype.slice.call(arguments, 1);
return window[name].call(this, ...args);
;
function sayHello(name, age)
console.log('hello ' + name + ', your\'e age is ' + age);
return some;
console.log(call_function('sayHello', 'john', 30)); // hello john, your'e age is 30
【讨论】:
【参考方案10】:试试这些
使用动态名称调用函数,如下所示:
let dynamic_func_name = 'alert';
(new Function(dynamic_func_name+'()'))()
带参数:
let dynamic_func_name = 'alert';
let para_1 = 'HAHAHA';
let para_2 = 'ABCD';
(new Function(`$dynamic_func_name('$para_1','$para_2')`))()
运行动态代码:
let some_code = "alert('hahaha');";
(new Function(some_code))()
【讨论】:
【参考方案11】:这是一个有效且简单的解决方案,用于检查函数是否存在并通过另一个函数动态地对该函数进行分类;
触发函数
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');">
【讨论】:
【参考方案12】:试试这个:
var fn_name = "Colours",
fn = eval("populate_"+fn_name);
fn(args1,argsN);
【讨论】:
使用这种模式有什么意义?我读过eval
函数有一些与其使用相关的奇怪副作用。我通常会尽量远离它,除非是万不得已。
评估动态内容使黑客很容易将自己的代码注入并执行到您的代码中以上是关于如何在 Javascript 中调用动态命名的方法?的主要内容,如果未能解决你的问题,请参考以下文章
从命名空间调用方法以在另一个 javascript 文件中使用