The arguments parameter
The arguments parameter is a collection of all the arguments passed to the function. The collection has a property named length
that contains the count of arguments, and the individual argument values can be obtained using an array indexing notation. Okay, we lied a bit. The arguments parameter is not a JavaScript array, and if you try to use array methods on arguments, you'll fail miserably. You can think of arguments as an array-like structure. This makes it possible to write functions that take an unspecified number of parameters. The following snippet shows you how you can pass a variable number of arguments to the function and iterate through them using an arguments array:
var sum = function () { var i, total = 0; for (i = 0; i < arguments.length; i += 1) { total += arguments[i]; } return total; }; console.log(sum(1,2,3,4,5,6,7,8,9)); // prints 45 console.log(sum(1,2,3,4,5)); // prints 15
As we discussed, the arguments parameter is not really an array; it is possible to convert it to an array as follows:
var args = Array.prototype.slice.call(arguments);
Once converted to an array, you can manipulate the list as you wish.
The this parameter
Whenever a function is invoked, in addition to the parameters that represent the explicit arguments that were provided on the function call, an implicit parameter named this
is also passed to the function. It refers to an object that's implicitly associated with the function invocation, termed as a function context. If you have coded in Java, the this
keyword will be familiar to you; like Java, this
points to an instance of the class in which the method is defined.
Equipped with this knowledge, let's talk about various invocation methods.
Invocation as a function
If a function is not invoked as a method, constructor, or via apply()
or call()
, it's simply invoked as a function:
function add() {} add(); var substract = function() { }; substract();
When a function is invoked with this pattern, this
is bound to the global object. Many experts believe this to be a bad design choice. It is natural to assume that this
would be bound to the parent context. When you are in a situation such as this, you can capture the value of this
in another variable. We will focus on this pattern later.
Invocation as a method
A method is a function tied to a property on an object. For methods, this
is bound to the object on invocation:
var person = { name: 'Albert Einstein', age: 66, greet: function () { console.log(this.name); } }; person.greet();
In this example, this
is bound to the person object on invoking greet
because greet
is a method of person. Let's see how this behaves in both these invocation patterns.
Let's prepare this HTML and JavaScript harness:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>This test</title> <script type="text/javascript"> function testF(){ return this; } console.log(testF()); var testFCopy = testF; console.log(testFCopy()); var testObj = { testObjFunc: testF }; console.log(testObj.testObjFunc ()); </script> </head> <body> </body> </html>
In the Firebug console, you can see the following output:
The first two method invocations were invocation as a function; hence, the this
parameter pointed to the global context (Window
, in this case).
Next, we define an object with a testObj
variable with a property named testObjFunc
that receives a reference to testF()
—don't fret if you are not really aware of object creation yet. By doing this, we created a testObjMethod()
method. Now, when we invoke this method, we expect the function context to be displayed when we display the value of this
.
Invocation as a constructor
Constructor functions are declared just like any other functions and there's nothing special about a function that's going to be used as a constructor. However, the way in which they are invoked is very different.
To invoke the function as a constructor, we precede the function invocation with the new keyword. When this happens, this
is bound to the new object.
Before we discuss more, let's take a quick introduction to object orientation in JavaScript. We will, of course, discuss the topic in great detail in the next chapter. JavaScript is a prototypal inheritance language. This means that objects can inherit properties directly from other objects. The language is class-free. Functions that are designed to be called with the new
prefix are called constructors. Usually, they are named using PascalCase as opposed to CamelCase for easier distinction. In the following example, notice that the greet
function uses this to access the name
property. The this
parameter is bound to Person
:
var Person = function (name) { this.name = name; }; Person.prototype.greet = function () { return this.name; }; var albert = new Person('Albert Einstein'); console.log(albert.greet());
We will discuss this particular invocation method when we study objects in the next chapter.
Invocation using apply() and call() methods
We said earlier that JavaScript functions are objects. Like other objects, they also have certain methods. To invoke a function using its apply()
method, we pass two parameters to apply()
: the object to be used as the function context and an array of values to be used as the invocation arguments. The call()
method is used in a similar manner, except that the arguments are passed directly in the argument list rather than as an array.