Josh Smeaton
Josh Smeaton

Reputation: 48720

Calling a Javascript function with an unknown number of arguments with original context

I'm currently using Function.apply to call a function with a dynamic number of arguments, but I do not have access to the original context, and have no desire to set the context myself. What I would like, is to be able to call a function with a variable number of arguments, keeping the original context.

Perhaps some code should show you what I'm trying to do:

function MulticastDelegate() {
    var handlers = [];

    this.event = {
        subscribe: function(handler) {
            if (typeof(handler) === 'function') {
                handlers.push(handler);
            }
        },
        unsubscribe: function(handler) {
            if (typeof(handler) === 'function') {
                handlers.splice(handlers.indexOf(handler),1);
            }
        }
    }

    this.execute = function() {
        var args = Array.prototype.slice.call(arguments);
        for (var handler in handlers) {
            // call this with the original context of the handler
            handlers[handler].apply(null, args);
        }
    }
}

Essentially, I want the behaviour of apply - the ability to pass an array of arguments - without the behaviour of call - changing the context under which a function executes.

Upvotes: 6

Views: 498

Answers (2)

Fabiano Soriani
Fabiano Soriani

Reputation: 8562

Could it be, that .bind would solve the case? http://documentcloud.github.com/underscore/#bind
In this case, you get a function 'binded' to the original context

Upvotes: 0

Daniel Brockman
Daniel Brockman

Reputation: 19270

There is no such thing as “the original context” of a function. You would have to do something like this:

subscribe: function(handler, context) {
    if (typeof(handler) === 'function') {
        handlers.push([handler, context]);
    }
},

And then, of course,

handlers[handler][0].apply(handlers[handler][1], args);

Alternatively (this is what I would do), leave it to the caller to make sure the handler has the right context. For example, instead of delegate.subscribe(this.foo), say

var self = this
delegate.subscribe(function () { self.foo() })

Or, using Function.prototype.bind,

delegate.subscribe(this.foo.bind(this))

Upvotes: 5

Related Questions