Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. 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.

like image 290
Rob Avatar asked Feb 27 '12 12:02

Rob


2 Answers

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:

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
like image 153
pimvdb Avatar answered Nov 11 '22 12:11

pimvdb


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);
like image 34
Rob W Avatar answered Nov 11 '22 11:11

Rob W