Introduction
This is the third post in the series of posts based on the book JavaScript -
The Good Parts by Douglas Crockford. The previous post covered details
of how one can create and use functions in JavaScript. This post details out the
features of functions in JavaScript. JavaScript functions have features which
are not present in other languages and one needs to understand these details to
write better JavaScripts and to understand the JavaScript written in the
JavaScript libraries.
Arguments to a Function In addition to the explicit parameters passed to a function two more parameters are passed to a function.
Invoking a function through "call" function of JavaScript
A method can be executed using the "call" of JavaScript.
When a global function is invoked
When a function defined in a global scope is invoked the value of "this" is the global object.
When Function is invoked as a method
When the function is defined inside another function it is called a method. When such a function is invoked the parent function is the value of "this". All the attributes and function defined in the parent scope are accessible to this function through the "this" object.
If one has an inner function in a method then the "this" for this inner function will be the method. For the inner function to have access to the outer parent function of the method the method must expose it as its local variable. Typically this variable is called "that"
Example:
"this" value in function "helper" will be "double".
The function "helper" does not have direct access to myObject. It will have access to only the local variables of the function double. Unless double exposes the myObject through "that" helper method will not have access to myObject.
When function is invoked as a new
Although JavaScript provides prototype based inheritance it provides the classical way of instantiating an object using the "new" keyword. When a function is invoked using the "new" keyword the value of "this" will be the object that is created out of this invocation.
When function is invoked using the "apply" or "call" method
All functions can be invoked via apply or call method. The difference between apply and call is that apply takes an array for the list of arguments to the function being invoked and call takes individual arguments instead of an array.
Invoking using "call"
Invoking using "apply"
Example of using "call"
The argument "arguments" In addition to "this" "arguments" is another variable that is available in each method. This is a list of arguments passed to the method. "arguments" is not an array in a true sense although it does behave array like. So functions that are normally available in array are not available with this variable.
Return from a function Every JavaScript function returns a value irrespective of whether there is a return statement or not. For functions that do not return anything this value is "undefined".
The only exception is when a function is invoked with a "new" does not return anything. The "this", the object created, is returned.
Pass by Reference All objects are always passed by reference. All primitive variables are passed by value.
Passing variables Passing variables is Pass by Value.
Passing
Object
Passing objects is pass by reference.
So how do we achieve this?
Option 1: When you know the method If you know the method of the object that will be called then it"s fairly easy. Just pass in the object instead of the function and call that instead. Using the objectchanger from the last example you"d get the following:
Here"s our objectchanger function one more time:
Arguments to a Function In addition to the explicit parameters passed to a function two more parameters are passed to a function.
- this: The value of this variable is discussed in detail below
- arguments: This is an Array like variable which has the list of arguments passed to the function
Invoking a function through "call" function of JavaScript
A method can be executed using the "call" of JavaScript.
When a global function is invoked
When a function defined in a global scope is invoked the value of "this" is the global object.
When Function is invoked as a method
When the function is defined inside another function it is called a method. When such a function is invoked the parent function is the value of "this". All the attributes and function defined in the parent scope are accessible to this function through the "this" object.
If one has an inner function in a method then the "this" for this inner function will be the method. For the inner function to have access to the outer parent function of the method the method must expose it as its local variable. Typically this variable is called "that"
Example:
myObject.double = function () { var that = this; //this is myObject var helper = function () { that.value = add(that.value, that.value); } helper(); }"this" value in function "double" will be myObject.
"this" value in function "helper" will be "double".
The function "helper" does not have direct access to myObject. It will have access to only the local variables of the function double. Unless double exposes the myObject through "that" helper method will not have access to myObject.
When function is invoked as a new
Although JavaScript provides prototype based inheritance it provides the classical way of instantiating an object using the "new" keyword. When a function is invoked using the "new" keyword the value of "this" will be the object that is created out of this invocation.
When function is invoked using the "apply" or "call" method
All functions can be invoked via apply or call method. The difference between apply and call is that apply takes an array for the list of arguments to the function being invoked and call takes individual arguments instead of an array.
Invoking using "call"
someFunction.call(thisArg[, arg1[, arg2[, ...]]]);The thisArg1 is the object that will be passed as the value of "this" to the function someFunction
Invoking using "apply"
someFunction.apply(thisArg, [arguments]);The thisArg1 is the object that will be passed as the value of "this" to the function someFunction
Example of using "call"
var Quo = function (string) { this.status = string; } Quo.prototype.getStatus = function () { return this.status; } var statusObject = {status: "A-OK"}; //statusObject does not inherit from Quo.prototype, but we can invoke getStatus and get the value //of status as follows: var status = Quo.prototype.getStatus.call(statusObject); //the value of status will be "A-OK".An example for apply will look the same, except that the arguments will be passed as an array.
The argument "arguments" In addition to "this" "arguments" is another variable that is available in each method. This is a list of arguments passed to the method. "arguments" is not an array in a true sense although it does behave array like. So functions that are normally available in array are not available with this variable.
Return from a function Every JavaScript function returns a value irrespective of whether there is a return statement or not. For functions that do not return anything this value is "undefined".
The only exception is when a function is invoked with a "new" does not return anything. The "this", the object created, is returned.
Pass by Reference All objects are always passed by reference. All primitive variables are passed by value.
Passing variables Passing variables is Pass by Value.
function myfunction(x){ // x is equal to 4 x = 5; // x is now equal to 5 } var x = 4; alert(x); // x is equal to 4 myfunction(x); alert(x); // x is still equal to 4
function myobject() { this.value = 5; } var o = new myobject(); alert(o.value); // o.value = 5 function objectchanger(fnc) { fnc.value = 6; } objectchanger(o); alert(o.value); // o.value is now equal to 6
Passing
functions
Passing functions is a little more complicated. See the example below to
understand how it functions, why it functions and how to actually achieve pass
by reference.function myobject() { this.value = 5; } myobject.prototype.add = function() { this.value++; } var o = new myobject(); alert(o.value); // o.value = 5 o.add(); alert(o.value); // o.value = 6 function objectchanger(fnc) { fnc(); // runs the function being passed in } objectchanger(o.add); alert(o.value); // sorry, still just 6
Why
does this happen?
The problem here is the use of the "this" keyword. It"s a handy short-hand
for referring to the current object context. When passing a function as a
parameter, though, the context is lost. More accurately, "this" now refers to
the context of the object making the call instead of the object's function we
just passed in. For standalone functions, this would be the window object and
for functions called from an event, this would be the event object.So how do we achieve this?
Option 1: When you know the method If you know the method of the object that will be called then it"s fairly easy. Just pass in the object instead of the function and call that instead. Using the objectchanger from the last example you"d get the following:
function objectchanger(obj) { obj.add(); // runs the method of the object being passed in } objectchanger(o); alert(o.value); // the value is now 7Option 2: When you don"t know the method If you don"t know the method of the object being passed in then you need to pass both the method and the object as parameters and use the call method. call is part of the JavaScript specification and allows a function to run in the context of another object. As a result, the this keyword will reference the right object: the object we passed in.
Here"s our objectchanger function one more time:
function objectchanger(fnc, obj) { fnc.call(obj); // runs the method of the object being passed in } objectchanger(o.add, o); alert(o.value); // the value is now 7Note the use of the method call.
No comments:
Post a Comment