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.
To pass an unknown number of arguments into a JavaScript function, we can use the rest syntax to make a function accept an infinite number of arguments. We have the printNames method that takes the names arguments array. The 3 dots before names indicates that names is an array of arguments.
length property provides the number of arguments actually passed to a function.
When you call a function in JavaScript, you can pass in any number of arguments, regardless of what the function declaration specifies. There is no function parameter limit. In the above function, if we pass any number of arguments, the result is always the same because it will take the first two parameters only.
A variadic function is a function where the total number of parameters are unknown and can be adjusted at the time the method is called. The C programming language, along with many others, have an interesting little feature called an ellipsis argument.
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))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With