Yesterday we were having a discussion about how we can extend Backbone.js so that we can have a separate controller with action methods the way we have in ASP.NET MVC rather putting the callbacks to be executed based on route matching in the Backbone.Router.One point which I mentioned casually is , “Javascript” does not sophisticated reflection like C# so that we can build a Router/Action Selector/Action Invoker/Controller sort of a pipeline.Later I thought that was very casual statement and not a very correct one.The kind of language Javascript is we do not need that kind of reflection and Javascript offers various ways to dynamically invoke functions.In this post we will explore different mechanisms of invoking functions in Javascript. We will start with the following simple code.
Here the “execute” function calls “func” and the function “func” defined in T is executed. Now let’s try to tweak the function “execute” in such a way so that it will accept a object and a function name as parameter and execute that function defined in that object.
Here we are using the “apply” function of Javascript which is available for any function object. The definition of apply is as shown below:
apply([thisObj[,argArray]]) where
- thisObj is the object that will be used as "this" i.e. object on which the function will be invoked
- argArray is the argument array used to pass argument values to the function which is invoked
“obj[func]” retrieves the function object based on the function name from the hash of “obj” and then “apply” is invoked on that function object.
As a next step let’s modify our function to accept few parameters.
The parameters are passed using the array “p”.
There is another Javascript function “call” which can be invoked on any function object to bind a particular object to it. This is defined as:
call([thisObj[, arg1[, arg2[, [, argN]]]]]) where
- thisObj (optional) - The object to be used as the current object on which the function is invoked
- arg1, arg2, , argN (optional list) - A list of arguments to be passed to the method.
The main difference with “apply” is in the way the parameters are handled, instead of a parameter array it accepts individual parameters.This makes it rigid compared to “apply”.
The following code shows the use of call.
If you are using Underscore.js this can be achieved more easily with _.bind function.
_.bind(function, object, *arguments) where
- function is the function object which needs to be invoked
- object is the current object on which the function is invoked
- *arguments are arguments values which the function expects
Our sample code is modified with _.bind
The _.bind function internally uses apply as shown below.