有很多关于动态调用函数的类似问题。但是,我无法找到解决我的具体问题的方法,其中我在闭包内部有本地函数,而不将函数暴露给我的对象的公共接口。
让我们看一些代码(这是一个虚构的例子)......
(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
};
我的想法已经不多了。非常感谢您的帮助和建议。
答案 0 :(得分:7)
私有函数是局部变量,不是任何对象的一部分。因此,访问属性的[...]
符号永远不会起作用,因为没有对象私有函数是属性。
相反,您可以创建两个对象: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
答案 1 :(得分:6)
您无法通过字符串获取对局部变量的引用。您必须将本地对象添加到命名空间:
(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);
答案 2 :(得分:2)
我很惊讶不正确的答案被标记为已接受。实际上,您可以通过字符串获取对局部变量的引用。只需使用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
时,我自己有一些非常具体的案例。
答案 3 :(得分:0)
您不能从定义它们的范围之外调用这些函数这一事实是javascript的基本组成部分,实际上是所有编程语言。
调用这些函数的唯一方法是将它们公开。然而,可以应用基于约定的方法。下划线前缀相当普遍,通常被理解为“不打算被称为公共函数”,例如:
obj._privateMethod1 = function(arg) {
//...
};
答案 4 :(得分:0)
假设您只有几个要调用的函数,则可以创建自己的Window版本来调用这些函数:
var myFuncs = {
'foo': foo,
'bar': bar
};
然后在您的代码中:
var s = 'foo';
myFuncs[s]();
只需确保在将功能添加到对象时定义了功能。在加载时不存在功能的模块中,可以在模块初始化时添加它们:
var myFuncs = {};
var init = function(){
myFuncs['foo'] = foo;
myFuncs['bar'] = bar;
}