【问题标题】:How to execute a private JavaScript function when I have its name as a string当我将其名称作为字符串时如何执行私有 JavaScript 函数
【发布时间】:2013-12-21 19:33:28
【问题描述】:

我正在尝试从返回的对象中执行一个私有函数。如果我提前知道函数的名称,这很容易,但在这种情况下,我不知道有哪些函数可用。我所拥有的是带有要调用的函数名称的字符串。有没有办法通过字符串调用这些函数?

function foo() {

  // some misc. chunk of valid javascipt code
  function bar() {
      console.log("hello");
  }
  // end misc. code

  // I would like to avoid doing this if I don't have to
  var executableFn = {};
  executableFn.test = function() {
    bar();
  }
  // end

  return {
    // This works but requires I know the name of the funciton ahead of time.
    // All I have is a string name of the function to call.
    funcRunner0: function() {
      bar();
    }, 
    // My ideal method for calling but does not work
    funcRunner1: function(functionName) {
      foo[functionName]();
    }, 
    // This works but I'm trying to avoid eval.  I'm not sure if this is not so bad
    funcRunner2: function(functionName) {
      var func = eval(functionName);
      func();
    },
    // This works.  I'm not sure if this is worse than funcRunner2 or the same;
    funcRunner3: function(functionName) {
      eval(functionName + "()");
    },
    // This works but requires the executableFn object which I would like to avoid if at all possible.
    funcRunner4: function(functionName) {
      executableFn[functionName]();
    }, 
  };
}

var bas = foo();

// This works but assumes I know the name of the function to call which I don't. 
bas.funcRunner0();
// This doesn't work
bas.funcRunner1("bar");
// This works
bas.funcRunner2("bar");
// This works
bas.funcRunner3("bar");
// This works but is not my ideal
bas.funcRunner4("test");

这些都是我想出的调用这个函数的方法。您认为我用字符串调用 bar 函数的最佳方法是什么?谢谢你的帮助。

【问题讨论】:

    标签: javascript private


    【解决方案1】:

    我理想的调用方法但不起作用

    foo[functionName]();
    

    是的,这是试图访问 foo 函数上的 [public] 属性。例如,它适用于 "call" 方法。

    这可行,但我试图避免评估。我不确定这是否还不错

    var func = eval(functionName);
    func();
    

    这行得通。我不确定这是否比 funcRunner2 差或相同;

    eval(functionName + "()");
    

    evals 的角度来看,两者都一样糟糕。选项 1 确实使处理参数变得更容易[不需要动态评估]。

    这可行,但需要 exec 对象,我希望尽可能避免。

    exec[functionName]();
    

    这就是这样做的方法。由于execfoo 范围内的局部变量,因此您甚至拥有自己的隐私。看来你也把exec 换成了publicObj

    // I would like to avoid doing this if I don't have to
    var publicObj = {};
    publicObj.test = function() {
        bar();
    }
    

    publicObj 变量,尽管它的名字,不是公共的 - 它是用 var 关键字声明为本地的!顺便说一句,您可以将其简化为

    var exec = {
        test: bar
    };
    

    【讨论】:

    • 是的。那是一个错字。固定的。 “这就是这样做的方法。”我想这就是我要确认的。我只是想确保没有一些棘手的方法可以使用我没有想到的字符串调用 bar 函数。
    【解决方案2】:

    为什么不创建一个私有命名空间(对象)并使用它来代替 exec/eval?

    function foo() {
    
        var private_ns = {
            bar : function() {
                console.log('bar', arguments);
            }
        };
    
        return {
            call_func: function(name) {
                if(name in private_ns) {
                    var args = [].slice.call(arguments, 1)
                    return private_ns[name].apply(null, args);
                } else {
                    console.error('no such function');
                }
            }
        };
    }
    
    var f = foo();
    
    > f.call_func('bar', 1, 2, 3);
    bar { '0': 1, '1': 2, '2': 3 }
    
    > f.call_func('noop');
    no such function
    

    【讨论】:

    • +1 用于展示他也可以将参数传递给函数的示例。
    • 是的。如果我对需要什么代码/结构强制执行规则,我可以这样做。我正在尝试查看是否有一种方法可以调用函数,而无需对代码的编写方式施加任何规则。有一种方法可以调用函数本身,所以我正在寻找一种方法来调用函数,如果你有一个字符串名称。
    • 没有 eval 是不可能的。
    【解决方案3】:

    这有点类似于您的“不理想”解决方案,但有点不同。如果将所有函数组织到一个对象中,则可以调用它们。不需要在对象中调用原始函数的另一个函数。

    http://jsfiddle.net/L3n4Z/

    function foo() {
    
        // all functions stored in this object
        var functions = {
            bar : function() {
              console.log("hello");
            }
        };
    
      return {
        funcRunner: function(funcName) {
          functions[funcName]();
        }
      };
    }
    
    var bas = foo();
    bas.funcRunner("bar");
    

    【讨论】:

    • 是的。如果我强制这是必须编写代码的方式,那么解决方案很简单。我只是在寻找一些不必执行某些结构/规则的鬼鬼祟祟的忍者方式。谢谢。
    猜你喜欢
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 2018-12-03
    • 1970-01-01
    • 2018-08-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多