CodingBison

Invoking a JavaScript function by directly using its name and passing arguments is not the only style for invoking a function. There are other styles of invoking functions as well.

We present three additional different styles of invoking a function: (1) invoking as an object method, (2) invoking as an object constructor, and (3) invoking an object function using call() and apply(). In the text that follows, we provide three sample examples, where we invoke functions using one of these styles.

In the first style, we can invoke function as an object method. Object methods are simply functions. Another way to look at object methods is that they are object properties but their value is actually a function.

Here is an example that assigns a previously defined function as a value to an object property.

 <!doctype html>
 <html>
 <div id="idDiv"></div>

 <script type="text/javascript"> 
 // Get a handle of the div element.
 var elem = document.getElementById("idDiv");

 // Define an object to store name/action pairs for magic beings!
 var objMagic = {"dragons": "fly", "wizards": "do magic", "griffins": "fly"};

 // Define a simple function 
 function funcMagicAction(doer) {elem.innerHTML += objMagic[doer];};

 // Define an object that has myAction as a method pointing to funcMagicAction. 
 var objDragon = {type: "dragons", myAction: funcMagicAction};

 // Call funcMagicAction as a method from the context of the object
 objDragon.myAction(objDragon.type);   // Prints "fly"
 </script>
 </html>

In the second style, we can invoke function as a constructor method of an object. Recall that a constructor returns a new object and since functions are nothing but objects, this approach works fine for creating a new objects. The argument passed to the function can be passed as an initial parameter to constructor. We can use the "this" keyword to add properties to the object.

We also need to use the "new" keyword when using a function as a constructor. Without this keyword, we would end up doing a simple assignment of the function's return value to the object!

 <!doctype html>
 <html>
 <div id="idDiv"></div>

 <script type="text/javascript"> 
 // Get a handle of the div element.
 var elem = document.getElementById("idDiv");

 // Define a function to return action of magical beings!
 function funcMagicBeing (argName, argAction) {
     this.beingName = argName;
     this.beingAction = argAction;
 }

 // Define an object using MagicBeing function as a constructor.
 var objMagic = new funcMagicBeing("griffin", "fly");

 // Access object properties.
 elem.innerHTML += objMagic.beingName;   // Prints "griffin". 
 elem.innerHTML += objMagic.beingAction; // Prints "fly". 
 </script>
 </html>

In the third style, we can invoke functions indirectly using call() and apply() methods. Both of these methods are properties of the Function.prototype and therefore, are available as properties for all functions.

In the example that illustrates the third invocation style, we define an object (objMagic) and a simple function (funcMagic()). When we invoke this function with call() and apply(), we pass objMagic as an argument to these calls. This function temporarily act as a method of the passed object. In fact, that is the reason why we use the keyword "this" to represent the object which forms the invocation context for these methods. In short, we can use these two methods only when we have an object in context and a function can potentially act as a method for that object.

There is another important point worth noting about comparison of these two methods. To illustrate this point, we use the next function: funcMagicWithArgs. For both call() and apply(), we can pass additional arguments to functions. With call(), we can simply separate multiple arguments (if present) with commas. With apply(), we need to pass arguments (one or more), in the form of an array.

Here is the example:

 <!doctype html>
 <html>
 <div id="idDiv"></div>

 <script type="text/javascript">
 // Get a handle of the div element.
 var elem = document.getElementById("idDiv");

 // Define an object to store name/action pairs for magic beings! 
 var objMagic = {"dragons": "fly", "wizards": "do magic", "griffins": "fly"};

 // Define a simple function. Note the usage of "this" keyword! 
 function funcMagic() {elem.innerHTML += this["griffins"];}

 // Invoke funcMagic using call() and apply(). 
 funcMagic.call(objMagic);   // Prints "fly".
 funcMagic.apply(objMagic);  // Prints "fly".

 // Redefine funcMagic to make it accept an argument. 
 function funcMagicWithArgs(param1) {elem.innerHTML += this[param1];}

 // Invoke funcMagicWithArgs using call() and pass an argument.
 funcMagicWithArgs.call(objMagic, "griffins");    // Prints "fly". 

 // Invoke funcMagicWithArgs using apply() and pass an argument as an array.
 funcMagicWithArgs.apply(objMagic, ["griffins"]); // Prints "fly". 
 </script>
 </html>

Since we can explicitly specify the method that we wish to invoke on an object, we can use the call()/apply() techniques to invoke a method defined by an object explicitly. Thus, if an object and its prototype were to define the same method, then invoking the method from the object would always result in invocation of the child's method. However, if we were to explicitly call the parent's method, then we can use specify the parent method, then specify the call followed by the object.

As an example, if parentObj is the parent object of the child object, childObj and both define a common method, cMethod(), then "childObj.cMethod()" would lead to invocation of the child method. However, if we wish to invoke the parents method, then we can invoke parentObj's own method using call and pass childObj as the object argument: "parentObj.cMethod.call(childObj)".





comments powered by Disqus