loading...

JavaScript – Invoking Functions

The JavaScript code that makes up the body of a function is not
executed when the function is defined but when it is invoked.
JavaScript functions can be invoked in four ways:

  • as functions,

  • as methods,

  • as constructors, and

  • indirectly through their call() and apply() methods.

Function Invocation

Functions are invoked as functions or as methods with an
invocation expression (Invocation Expressions). An
invocation expression consists of a function expression that
evaluates to a function object followed by an open parenthesis, a
comma-separated list of zero or more argument expressions, and a
close parenthesis. If the function expression is a property-access
expression—if the function is the property of an object or an
element of an array—then it is a method invocation expression. That
case will be explained below. The following code includes a number
of regular function invocation expressions:

printprops({x:1});                                 
var total = distance(0,0,2,1) + distance(2,1,3,5); 
var probability = factorial(5)/factorial(13);

In an invocation, each argument expression (the ones between
the parentheses) is evaluated, and the resulting values become the
arguments to the function. These values are assigned to the
parameters named in the function definition. In the body of the
function, a reference to a parameter evaluates to the corresponding
argument value.

For regular function invocation, the return value of the
function becomes the value of the invocation expression. If the
function returns because the interpreter reaches the end, the return
value is undefined. If the
function returns because the interpreter executes a return, the return value is the value of
the expression that follows the return or undefined if the return statement has no value.

For function invocation in ECMAScript 3 and nonstrict
ECMAScript 5, the invocation context (the this value) is the global object. In
strict mode, however, the invocation context is undefined.

Functions written to be invoked as functions do not typically
use the this keyword at all. It
can be used, however, to determine whether strict mode is in
effect:

// Define and invoke a function to determine if we're in strict mode.
var strict = (function() { return !this; }());

Method Invocation

A method is nothing more than a
JavaScript function that is stored in a property of an object. If
you have a function f and an
object o, you can define a method
named m of o with the following line:

o.m = f;

Having defined the method m() of the object o, invoke it like this:

o.m();

Or, if m() expects two
arguments, you might invoke it like this:

o.m(x, y);

The code above is an invocation expression: it includes a
function expression o.m and two
argument expressions, x and
y. The function expression is
itself a property access expression (Property Access Expressions), and this means that the function is
invoked as a method rather than as a regular function.

The arguments and return value of a method invocation are
handled exactly as described above for regular function invocation.
Method invocations differ from function invocations in one important
way, however: the invocation context. Property access expressions
consist of two parts: an object (in this case o) and a property name ( m). In a method invocation expression like
this, the object o becomes the
invocation context, and the function body can refer to that object
by using the keyword this. Here
is a concrete example:

var calculator = {  // An object literal
    operand1: 1,
    operand2: 1,
    add: function() {
        // Note the use of the this keyword to refer to this object.
        this.result = this.operand1 + this.operand2;
    }
};
calculator.add();       // A method invocation to compute 1+1.
calculator.result       // => 2

Most method invocations use the dot notation for property
access, but property access expressions that use square brackets
also cause method invocation. The following are both method
invocations, for example:

o["m"](x,y);   // Another way to write o.m(x,y).
a[0](z)        // Also a method invocation (assuming a[0] is a function).

Method invocations may also involve more complex property
access expressions:

customer.surname.toUpperCase(); // Invoke method on customer.surname
f().m();                        // Invoke method m() on return value of f()

Methods and the this
keyword are central to the object-oriented programming paradigm. Any
function that is used as a method is effectively passed an implicit
argument—the object through
which it is invoked. Typically, a method performs some sort of
operation on that object, and the method-invocation syntax is an
elegant way to express the fact that a function is operating on an
object. Compare the following two lines:

rect.setSize(width, height);
setRectSize(rect, width, height);

The hypothetical functions invoked in these two lines of code
may perform exactly the same operation on the (hypothetical) object
rect, but the method-invocation
syntax in the first line more clearly indicates the idea that it is
the object rect that is the
primary focus of the operation.

Method Chaining

When methods return objects, you can use the return value of
one method invocation as part of a subsequent invocation. This
results in a series (or “chain” or “cascade”) of method
invocations as a single expression. When working with the jQuery
library (Chapter 19), for example, it is common to
write code like this:

// Find all headers, map to their ids, convert to an array and sort them
$(":header").map(function() { return this.id }).get().sort();

When you write a method that does not have a return value of
its own, consider having the method return this. If you do this consistently
throughout your API, you will enable a style of programming known
as method chaining[11] in which an object can be named once and then
multiple methods can be invoked on it:

shape.setX(100).setY(100).setSize(50).setOutline("red").setFill("blue").draw();

Don’t confuse method chaining with constructor chaining,
which is described in Constructor and Method Chaining.

Note that this is a
keyword, not a variable or property name. JavaScript syntax does not
allow you to assign a value to this.

Unlike variables, the this
keyword does not have a scope, and nested functions do not inherit
the this value of the containing.
If a nested function is invoked as a method, its this value is the object it was invoked
on. If a nested function is invoked as a function then its this value will be either the global
object (non-strict mode) or undefined (strict mode). It is a common
mistake to assume that a nested function invoked as a function can
use this to obtain the invocation
context of the outer function. If you want to access the this value of the outer function, you need
to store that value into a variable that is in scope for the inner
function. It is common to use the variable self for this purpose. For
example:

var o = {                           // An object o.
    m: function() {                 // Method m of the object.
        var self = this;            // Save the this value in a variable.
        console.log(this === o);    // Prints "true": this is the object o.
        f();                        // Now call the helper function f().

        function f() {              // A nested function f
           console.log(this === o); // "false": this is global or undefined
           console.log(self === o); // "true": self is the outer this value.
        }
    }
};
o.m();                              // Invoke the method m on the object o.

Example 8-5, in The bind() Method,
includes a more realistic use of the var
self=this
idiom.

Constructor Invocation

If a function or method invocation is preceded by the keyword
new, then it is a constructor invocation. (Constructor
invocations were introduced in Object Creation Expressions and Creating Objects with new, and constructors will be
covered in more detail in Chapter 9.) Constructor
invocations differ from
regular function and method invocations in their handling of
arguments, invocation context, and return value.

If a constructor invocation includes an argument list in
parentheses, those argument expressions are evaluated and passed to
the function in the same way they would be for function and method
invocations. But if a constructor has no parameters, then JavaScript
constructor invocation syntax allows the argument list and
parentheses to be omitted entirely. You can always omit a pair of
empty parentheses in a constructor invocation and the following two
lines, for example, are equivalent:

var o = new Object();
var o = new Object;

A constructor invocation creates a new, empty object that
inherits from the prototype property of the
constructor. Constructor functions are intended to initialize
objects and this newly created object is used as the invocation
context, so the constructor function can refer to it with the
this keyword. Note that the new
object is used as the invocation context even if the constructor
invocation looks like a method invocation. That is, in the
expression new o.m(), o is not used as the invocation
context.

Constructor functions do not normally use the return keyword. They typically initialize
the new object and then return implicitly when they reach the end of
their body. In this case, the new object is the value of the
constructor invocation expression. If, however, a constructor
explicitly used the return
statement to return an object, then that object becomes the value of
the invocation expression. If the constructor uses return with no value, or if it returns a
primitive value, that return value is ignored and the new object is
used as the value of the invocation.

Indirect Invocation

JavaScript functions are objects and like all JavaScript
objects, they have methods. Two of these methods, call() and apply(), invoke the function indirectly.
Both methods allow you to explicitly specify the this value for the invocation, which means
you can invoke any function as a method of any object, even if it is
not actually a method of that object. Both methods also allow you to
specify the arguments for the invocation. The call() method uses its own argument list
as arguments to the function and the apply() method expects an array of values
to be used as arguments. The call() and apply() methods are described in detail in
The call() and apply() Methods.


[11] The term was coined by Martin Fowler. See http://martinfowler.com/dslwip/MethodChaining.html.

Comments are closed.

loading...