简体   繁体   English

在javascript中动态调用本地函数

[英]dynamically call local function in javascript

there are plenty of similar questions out there about calling functions by name dynamically. 关于按名称动态调用函数有很多类似的问题。 However, I can't find a solution to my specific problem where I have local functions inside a closure without exposing the functions to the public interface of my object. 但是,我无法找到解决我的具体问题的方法,其中我在闭包内部有本地函数,而不将函数暴露给我的对象的公共接口。

Lets see some code (this is a fictional example)... 让我们看一些代码(这是一个虚构的例子)......

(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 doesn't work because "this" is MyObject and the local functions are not exposed. 这不起作用,因为“this”是MyObject,并且不公开本地函数。 Also I'd like to be able to check if the function exists before trying to call it. 此外,我希望能够在尝试调用之前检查函数是否存在。 eg. 例如。

var func_name = 'privateMethod'+number;
if($.isFunction(this[func_name])) {
  this[func_name].apply(this,[otherarg]);
}

I'm not really sure how to proceed, short of exposing my private functions to the public interface, it all works then. 我不确定如何继续进行,除了将我的私有函数暴露给公共接口之外,它一切正常。

obj.privateMethod1 = function(arg) {
  //do something with arg
};

obj.privateMethod2 = function(arg) {
  //do something else with arg
};

I'm running out of ideas. 我的想法已经不多了。 Your help and advise is greatly appreciated. 非常感谢您的帮助和建议。

The private functions are local variables and not part of any object. 私有函数是局部变量,不是任何对象的一部分。 So, the [...] notation for accessing a property is never going to work since there is no object the private functions are properties of. 因此, [...]记法访问属性是从来没有去上班,因为没有对象的私有函数的性质。

Instead, you could make two objects: private and public : 相反,你可以制作两个对象: 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

You cannot get a reference to a local variable by a string. 您无法通过字符串获取对局部变量的引用。 You have to add the local objects to a namespace: 您必须将本地对象添加到命名空间:

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

I'm surprised that incorrect answer is marked as accepted. 我很惊讶不正确的答案被标记为已被接受。 Actually you CAN get a reference to a local variable by a string. 实际上,您可以通过字符串获取对局部变量的引用。 Just by using eval : 只需使用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);

Actually this code is very bad and in 99.9% cases you should not use eval . 实际上这个代码非常糟糕,99.9%的情况下你不应该使用eval But you must know how it works and what you can do with it. 但是你必须知道它是如何工作的以及你可以用它做什么。 I myself had a few very specific cases when usage of eval was necessary. 当我需要使用eval时,我自己有一些非常具体的案例。

Assuming you only have a couple of functions to call, you can create your own version of Window to use to call the functions: 假设您只有几个要调用的函数,您可以创建自己的Window版本来调用函数:

var myFuncs = {
    'foo': foo,
    'bar': bar
};

Then in your code: 然后在你的代码中:

var s = 'foo';
myFuncs[s]();

Just make sure the functions are defined when you add them to the object. 只需确保在将对象添加到对象时定义了这些函数。 In a module where the functions don't exist at load time, you can add them when the module is initialized: 在加载时不存在函数的模块中,可以在初始化模块时添加它们:

var myFuncs = {};
var init = function(){
    myFuncs['foo'] = foo;
    myFuncs['bar'] = bar;
}

The fact that you cannot call these functions from outside of the scope within which they are defined is a fundamental part of javascript, and indeed, all programming languages. 您不能从定义它们的范围之外调用这些函数的事实是javascript的基本部分,实际上是所有编程语言。

The only way to call these functions is to make them public. 调用这些函数的唯一方法是将它们公开。 A convention based approach can be applied instead however. 然而,可以应用基于约定的方法。 The underscore prefix is fairly ubiquitous and generally understood to mean "not intended to be called as a public function" eg: 下划线前缀相当普遍,通常被理解为“不打算被称为公共函数”,例如:

obj._privateMethod1 = function(arg) {
  //...
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM