在javascript中动态调用本地函数
Posted
技术标签:
【中文标题】在javascript中动态调用本地函数【英文标题】:dynamically call local function in javascript 【发布时间】:2012-03-16 22:05:05 【问题描述】:关于通过名称动态调用函数有很多类似的问题。但是,我无法找到解决我的特定问题的解决方案,即我在闭包中拥有本地函数而不将函数暴露给我的对象的公共接口。
让我们看一些代码(这是一个虚构的例子)...
(function(window,$)
MyObject = (function($)
var obj = ;
obj.publicMethod = function(number,otherarg)
this['privateMethod'+number].apply(this,[otherarg]);
;
var privateMethod1 = function(arg)
//do something with arg
;
var privateMethod2 = function(arg)
//do something else with arg
;
return obj;
)($);
window.MyObject = MyObject;
)(window,jQuery);
这不起作用,因为“this”是 MyObject 并且本地函数未公开。 此外,我希望能够在尝试调用它之前检查该函数是否存在。 例如。
var func_name = 'privateMethod'+number;
if($.isFunction(this[func_name]))
this[func_name].apply(this,[otherarg]);
我不确定如何继续,除了将我的私有函数暴露给公共接口之外,一切正常。
obj.privateMethod1 = function(arg)
//do something with arg
;
obj.privateMethod2 = function(arg)
//do something else with arg
;
我的想法已经不多了。非常感谢您的帮助和建议。
【问题讨论】:
【参考方案1】:私有函数是局部变量而不是任何对象的一部分。因此,用于访问属性的 [...]
符号永远不会起作用,因为没有对象是私有函数的属性。
相反,您可以创建两个对象:private
和 public
:
var public = ,
private = ;
public.publicMethod = function(number, otherarg)
// `.apply` with a fixed array can be replaced with `.call`
private['privateMethod' + number].call(this, otherarg);
;
private.privateMethod1 = function(arg)
//do something with arg
;
private.privateMethod2 = function(arg)
//do something else with arg
;
return public; // expose public, but not private
【讨论】:
这么直截了当...我一直在唱这个咒语,以至于我忘记了它的意思。【参考方案2】:您无法通过字符串获取对局部变量的引用。您必须将本地对象添加到命名空间:
(function(window,$)
// Use "var MyObject = " instead of "MyObject = "!! Otherwise, you're assigning
// the object to the closest parent declaration of MyVar, instead of locally!
var MyObject = (function($)
var obj = ;
var local = ; // <-- Local namespace
obj.publicMethod = function(number,otherarg)
local['privateMethod'+number].call(this, otherarg);
;
var privateMethod1 = local.privateMethod1 = function(arg)
//do something with arg
;
var privateMethod2 = local.privateMethod2 = function(arg)
//do something else with arg
;
return obj;
)($);
window.MyObject = MyObject;
)(window,jQuery);
【讨论】:
澄清一下,您不再需要别名声明var privateMethodX
,因为它们是 local
的一部分;我假设他们仍然在这个例子中进行比较。【参考方案3】:
我很惊讶不正确的答案被标记为已接受。实际上,您可以通过字符串获取对局部变量的引用。只需使用eval
:
(function(window,$)
MyObject = (function($)
var obj = ;
obj.publicMethod = function(number,otherarg)
// Gets reference to a local variable
var method = eval('privateMethod'+number);
// Do with it whatever you want
method.apply(this,[otherarg]);
;
var privateMethod1 = function(arg)
//do something with arg
;
var privateMethod2 = function(arg)
//do something else with arg
;
return obj;
)($);
window.MyObject = MyObject;
)(window,jQuery);
实际上这段代码非常糟糕,在 99.9% 的情况下你不应该使用eval
。但是你必须知道它是如何工作的以及你可以用它做什么。当需要使用eval
时,我自己也遇到过一些非常具体的情况。
【讨论】:
这个问题很旧,但是,接受的答案有什么问题?它被广泛接受为 javascript 对象上公共/私有方法的正确方法。 其实我的抱怨是反对“你不能通过字符串获得对局部变量的引用”。这不是真的,你可以。正如我所写:使用eval
是非常糟糕的做法,但您必须知道如何使用它。使用eval
,您可以通过字符串访问局部变量。我认为这个答案可能会误导其他 javascript 用户。答案的另一部分怎么样 - 它是正确的(虽然我认为@pimvdb 变体更好一点,但这并不重要)。【参考方案4】:
您不能从定义它们的范围之外调用这些函数这一事实是 javascript 的一个基本部分,事实上,所有编程语言也是如此。
调用这些函数的唯一方法是将它们公开。然而,可以改为应用基于约定的方法。下划线前缀相当普遍,通常被理解为“不打算作为公共函数调用”,例如:
obj._privateMethod1 = function(arg)
//...
;
【讨论】:
【参考方案5】:假设您只有几个函数要调用,您可以创建自己的 Window 版本来调用这些函数:
var myFuncs =
'foo': foo,
'bar': bar
;
然后在你的代码中:
var s = 'foo';
myFuncs[s]();
只需确保在将函数添加到对象时定义它们即可。在加载时函数不存在的模块中,您可以在模块初始化时添加它们:
var myFuncs = ;
var init = function()
myFuncs['foo'] = foo;
myFuncs['bar'] = bar;
【讨论】:
以上是关于在javascript中动态调用本地函数的主要内容,如果未能解决你的问题,请参考以下文章
Asp.net MVC 5 动态创建按钮并调用带有参数的 javascript 函数