在javascript中动态调用本地函数

时间:2012-02-27 12:20:14

标签: javascript closures scope

有很多关于动态调用函数的类似问题。但是,我无法找到解决我的具体问题的方法,其中我在闭包内部有本地函数,而不将函数暴露给我的对象的公共接口。

让我们看一些代码(这是一个虚构的例子)......

(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
};

我的想法已经不多了。非常感谢您的帮助和建议。

5 个答案:

答案 0 :(得分:7)

私有函数是局部变量,不是任何对象的一部分。因此,访问属性的[...]符号永远不会起作用,因为没有对象私有函数是属性。

相反,您可以创建两个对象:privatepublic

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