3

I am trying to dynamically call a function inside of an object. Found the apply function but not fully understanding it. Check out the code below, by triggering Test.checkQueue() it should in turn call showSomething "method". Thanks.

var Test = {    
    , queue : [{action:'showSomething', id:'1234'},{action:'showOther', id:'456'}]
    , showSomething: function(what) {
        alert(what);    
    }
    , checkQueue : function() {
        console.log('checkQueue');
        console.log(this.queue);
        if (this.queue.length) {
            var do = this.queue.shift();
            console.log(do);
            // action.action(action.id);
            do.action.apply(this, do.id || []);
        }
    }

};
Richard JP Le Guen
  • 28,364
  • 7
  • 89
  • 119
Louis W
  • 3,166
  • 6
  • 46
  • 76

2 Answers2

3

There are (at least) two problems with your use of apply here.

  1. It is a method of a function object, and you seem to be calling it on strings

  2. It always takes an array as its second parameter -- you are passing in either a string or an empty array.

Try calling it like this:

Test[do.action].apply(this, do.id ? [do.id] : []);

Using Test[do.action] will access the actual function, rather than the string "showSomething" or "showOther", and do.id ? [do.id] : [] will always return an array.

Ian Clelland
  • 43,011
  • 8
  • 86
  • 87
  • 1
    Alternatively, the OP could use `call` instead of `apply` to avoid the array issue – Justin Johnson Dec 10 '09 at 23:37
  • Actually you don't need `apply` nor `call`, since the function call is being made on an object instance (`Test`), the context (the `this` keyword) will be set *implicitly* on that function, there is no need to set it *explicitly*, eg. `Test[obj.action](obj.id);`. – Christian C. Salvadó Dec 11 '09 at 00:37
2

The problem is that do.action is a string, not a function. You could change your code in one of two ways.

  1. Instead of storing the name of the function in your queue, actually store the function:

    queue : [ { action: this.showSomething ...
    

    You might need to make sure that it has been defined first or something like that, though.

  2. Resolve the string back to the actual property:

    this[do.action].apply(...)
    
nickf
  • 537,072
  • 198
  • 649
  • 721
  • Appreciate the help, I am accepting the first post but I might also use your "this", so I don't have to hard code the "class" name. – Louis W Dec 10 '09 at 23:53