简体   繁体   中英

How to execute a private JavaScript function when I have its name as a string

I'm trying to execute an private function from within the returned object. If I knew the name of the function ahead of time this is easy but in this case I won't know what functions are available. What I have is the a string with the name of the function to call. Is there a way to call these functions via a string?

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

These are all the ways I have come up with to call this function. What do you think is the best way for me to call the bar function with a string? Thanks for you help.

My ideal method for calling but does not work

 foo[functionName](); 

Yes, that's trying to access a [public] property on the foo function. It would work with the "call" method, for example.

This works but I'm trying to avoid eval. I'm not sure if this is not so bad

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

This works. I'm not sure if this is worse than funcRunner2 or the same;

 eval(functionName + "()"); 

Both are as bad as the other from eval s perspective. Option 1 just does make it easier to work with arguments [which need not be dynamically evaluated].

This works but requires the exec object which I would like to avoid if at all possible.

 exec[functionName](); 

That's just the way to do it. Since exec is a local variable in the foo scope, you even have your privateness. It seems you have switched exec for publicObj as well

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

The publicObj variable is, despite its name, not public - it's declared local with the var keyword! Btw, you could've simplified this to

var exec = {
    test: bar
};

Why not make a private namespace (object) and use that instead of 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

It's somewhat similar to your "not ideal" solution, but is a bit difference. If you organize all of your functions into an object, you can then call them. No need for another function within an object that calls the original function.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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