3

So I have the following pseudo Javascript code:

var Class = (function(window, document, $) {
    function meth_1()
    {
        //some code
    }

    function meth_2()
    {
        //some code
    }

    function meth_3()
    {
        //some code
    }

    function meth_4()
    {
        //some code to call other three functions dynamically
    }

    Class = {
        meth_1: meth_1,
        meth_2: meth_2,
        meth_3: meth_3,
        meth_4: meth_4
    };
    return Class;

})(window, document, jQuery);

In the meth_4 function, I want to call the other 3 functions dynamically by passing the function name as a string. How can I do this?!

In this related StackOverflow question, the answer provides a solution to how this could be done in window scope i.e. window[function_name](). However, I'd like to know how I can do it in my particular circumstance.

Thanks.

EDIT

The answer I selected works ok. You could also do the following:

var Class = (function(window, document, $) {
    var meth_func = {
        meth_1: function(){/**your code**/},
        meth_2: function(){/**your code**/},
        meth_3: function(){/**your code**/}            
    }

    function meth_4(func_name)
    {
        meth_func[func_name]();
    }

    Class = {
        meth_4: meth_4
    };
    return Class;

})(window, document, jQuery);

This would probably work better if you wanted to make private those three functions being called dynamically.

Community
  • 1
  • 1
ObiHill
  • 11,448
  • 20
  • 86
  • 135
  • 1
    Why don't you just create an array of functions? – Lee Taylor Mar 04 '13 at 13:43
  • 1
    @LeeTaylor How?! Can you post an answer on that?! – ObiHill Mar 04 '13 at 13:49
  • to make it clear, you are looking for an Execute function, so that meth4 body could be : Execute("Class.meth_1"); Execute("class.meth_2");... ? – jbl Mar 04 '13 at 13:53
  • @jbl I'm not sure I understand you. I want to call the first three functions in a dynamic way from the fourth using only the function name. Just like I can use `window[function_name]()` is there an alternative for when I want to do the same thing within `meth_4`. – ObiHill Mar 04 '13 at 14:12

3 Answers3

2

Since you want to call functions using bracket notation in object scope, not window scope, you can use this instead of window:

function meth_4()
{
    this["meth_1"]();
    this["meth_2"]();
    this["meth_3"]();
}
Frédéric Hamidi
  • 258,201
  • 41
  • 486
  • 479
  • @FrédéricHamidi Thanks for this. However, this won't work for what I'm trying to do because I'm trying to call the other 3 functions for use within this function i.e. `meth_4`, and not when I call `Class.meth_4();`. The earlier deleted comment by @Quentin is actually right. – ObiHill Mar 04 '13 at 14:03
  • 1
    @Chuck, using `this` should still work in this situation, unless you're explicitly decoupling the method from its object before calling it (e.g. with `var meth_4 = Class.meth_4; meth_4();` or through `call()`, `apply()` or `bind()`). Is this the case? – Frédéric Hamidi Mar 04 '13 at 14:07
  • @FrédéricHamidi I need the values returned from `meth_1`, `meth_2`, and `meth_3` for usage inside `meth_4`...I hope that makes it clearer?! – ObiHill Mar 04 '13 at 14:17
  • 2
    @Chuck, not really :) Values returned from `meth_1()`, `meth_2()` and `meth_3()` can be used by `meth_4()` since it is their caller. You only have to write something like `var meth_1_result = this["meth_1"]();` then use that variable within `meth_4()`. – Frédéric Hamidi Mar 04 '13 at 14:22
  • For example, I need to do something like `var func_name = "meth_1"; var res_meth_1 = this[func_name]();` – ObiHill Mar 04 '13 at 14:23
  • @Chuck, well, that would indeed work as you expect, and you can use `res_meth_1` within `meth_4()` as you would with any other local variable. Well, unless `func_name` is captured by an unprotected closure inside a loop, but that's a whole other story. – Frédéric Hamidi Mar 04 '13 at 14:25
  • Ok, got it to work, what I posted here was pseudo-code so I hadn't fully updated my code properly. Do you know how I could do this if I made those 3 functions private i.e. `Class = { meth_4: meth_4 }; return Class;` instead of `Class = { meth_1: meth_1, meth_2: meth_2, meth_3: meth_3, meth_4: meth_4 }; return Class;` – ObiHill Mar 04 '13 at 14:35
  • @Chuck, then the other functions would be private, and only accessible from the scope they're defined in. You would not be able to access them from any other code. However, in your current code `meth_4()` is defined in the same scope, so it could access them. – Frédéric Hamidi Mar 04 '13 at 14:37
  • Yeah, I know. I was hoping there was someway I could restrict access to those functions i.e. I won't be able to call `Class.meth_3()`, but I would still be able to access those same functions from `meth_4` in a dynamic way?! – ObiHill Mar 04 '13 at 14:44
  • @Chuck, sorry, it took time for me to understand your last point. You will not be able to access the private functions through `this`, since they're not members of the context object. `meth_4()` can still call them "directly", though. – Frédéric Hamidi Mar 04 '13 at 18:25
  • Ok Thanks. I managed to find a way to get it done which I posted as an edit. Cheers. – ObiHill Mar 04 '13 at 18:54
0

I don't know why you would want that (also 'Class' is not good as a variable name), but could be done like this:

var Class = (function (window /*, ... */) {
  return {
    func1: function () {console.log('1')}
  , func2: function () {console.log('2')}
  , func3: function () {console.log('3')}
  , func4: function (funcName) {
      console.log('4+')
      this[funcName]()
    }
  }
})(window)

Class.func4('func3')
strandel
  • 21
  • 2
0

Here's an implementation that can do what you want. If you pass a string it will simply look up the appropriate function and execute it. However since functions in JS are indeeed objects them self you can pass those around and to show that I've extended the functionality a bit compared to what you ask for. If you pass a function (actual anything but a string) it will (try to) invoke it

meth_4 = function(fun){
   if(typeof fun === 'string'){
       this[fun](args.slice(1));
   } else { //assuming it's a function
       if(arguments.length == 1)
          fun.call(this,[])
       } else {
          fun.apply(this,arguments.slice(1))  
       }
   }
}

JavaScript objects are, or at can be treated as, a key/value pair collection. Any function or property can be access in two semantically equivalent ways

obj.key or obj["key"] in certain cases only the latter can be used. E.g. if the property is called property nameyou can't do obj.property name but can do obj["property name"]

Rune FS
  • 21,497
  • 7
  • 62
  • 96