Javascript - Functions

javascript

Invocation
Return Value

function functionName(p1, p2, p3) {
  statements;
}

Function can take any number of parameters, and we do not have to define all 
the parameters when defining the function.

We do not have to specify the number of parameters when we declare a function.
A javascript function can take 0 or more named parameters. The function body 
can declare its own variables which are local to that function. The named 
parameters turn out to be more like a guideline. You can call a function without 
passing the parameters it expects, in which case they will be set to undefined. 
You can also pass in more arguments than the function is expecting.

Functions also have access to an additional variable inside their body called 
arguments, which is an array-like object holding all the values passed to the 
functions. The arguments object is a local variable available within all 
functions. You can refer to a function's arguments within the function by using 
the arguments object. This object contains an entry for each argument passed to 
the function, the first entry's index starting at 0.

The arguments object is not an array. It is similar to an array, but does not 
have any array properties except length. For example, it does not have the pop 
method.

// To determine the number of arguments that a function receive:
argument.length

// To determine the number of arguments that a function expects to receive:
functionName.length

// To convert the arguments variable into a real array:
var args = Array.prototype.slice.call(arguments);

// Function A call function B with the same argument list:
function b(){
}
function a(){
    b.apply(null, arguments);
}
a('fred', 'Sally', 'Jo');

Inner function declarations and expression result in function objects being 
created within the execution context of a function so they get more elaborate 
scope chains. Consider the following code, which defines a function with an 
inner function declaration and then executes the outer function:
function exampleOuterFunction(formalParameter) {
    function exampleInnerFunctionDec() {
        ... // inner function body
    }
    ... // the rest of the outer function body
}
exampleOuterFunction(5);
The function object corresponding with the outer function declaration is created 
during variable instantiation in the global execution context so its "scope" 
property contains the one item scope chain with only the global object in it.
When the global code executes the call to the exampleOuterFunction, a new 
execution context is created for that function call, and an Activation/Variable 
object along with it. The scope of that new execution context becomes the chain 
consisting of the new Activation object followed by the chain referred to by the 
outer function object's "scope" property (just the global object). Variable 
instantiation for that new execution context results in the creation of a 
function object that corresponds with the inner function definition and the 
"scope" property of that function object is assigned the value of the scope 
from the execution context in which it was created. A scope chains that contains 
the Activation object followed by the global object.
So far this is all automatic and controlled by the structure and execution of 
the source code. The scope chain of the execution context defines the scope 
property of the function object created, and the scope property of function 
object define the scope for their execution contexts (along with the 
corresponding Activation object).

If we have a function named x, to determine the number parameters that this
function expects, use x.length.  To determine the number of parameters that
were actually supplied to this function, use arguments.length.

// Adding method to native classes:
String.prototype.repeatify = String.prototype.repeatify || function(times) {
   var str = '';

   for (var i = 0; i < times; i++) {
      str += this;
   }

   return str;
};

// Functions are first-class objects:

In many traditional OO language, objects can contain data, and they can have 
methods.  In these languages, the data and methods are usually distinct concepts.  
JavaScript takes a different path.  Functions in JavaScript are considered 
objects like any other object types such as Strings, Numbers, or Dates.  
Like other objects, functions are defined by a JavaScript constructor, 
Function, and it can be used just like any other object or variables.  
Specifically, we can:

1. Assign a function to variables
2. Assign a function as property of an object
3. Pass a function as parameter
4. Return a function as a result of a function

Because function are treated in the same way as other objects, we say that 
functions are first-class-object.

// The function keyword:

The function keyword does not create a function with a name.  Consider:

function doSomethingWonderful() {
  // ...
}

It does not  create a function named 'doSomethingWonderful'.  Although the 
notation may seem familiar and it is ubiquitously used to create top-level 
functions, it's the same syntactic sugar used by the var keyword to create a 
property of the window object.  The function keyword automatically create a 
Function instance and assigns it to a property of the window object.  The above 
code is exactly as:

doSomethingWonderful = function() {
  // ...
};

A function literal is used to create an instance of Function and then assigned 
to the variable doSomethingWonderful in the same way that our Number literal 
123 was used to assigned to a Number instance.  The syntax for function literal 
consists of the keyword function, followed by its parameter list enclosed in 
parentheses, then followed by the function body.  In other words, the name of 
the function is not bound directly to the function itself.  The Function 
instance itself no more has a name than a Number literal or a String literal.

The best thing about JavaScript is its implementation of functions.  It got almost
everything right.  But, as you should expect with JavaScript, it didn't get 
everything right.  A function encloses a set of statements.  Functions are the 
fundamental modular unit of JavaScript.  They are used for code reuse, information
hiding, and composition.  Functions are used to specify the behavior of objects.
Generally, the craft of programming is the factoring of a set of requirements into
a set of functions and data structures.

Functions in JavaScript are objects.  Objects are collections of name-value pairs
having a hidden link to a prototype object.  Objects literals are linked to 
Object.prototype.  Function objects are linked to Function.prototype, which is 
itself linked to Object.prototype.  Every function is also created with to additional
hidden properties: the function context and the code that implements the function's
behavior.

Every function object is also created with a prototype property.  Its value is an object
with a constructor property whose value is the function.  This is distinct from the 
hidden link to Function.prototype.

Since functions are objects, they can be used like any other value.  Functions can be
stored in variables, objects, and arrays.  Functions can be passed as arguments to
functions, and functions can be returned from functions.  Also, because functions are
objects, functions can have methods.

The think that is special about function is that they can be invoked.

// Function Literal:

Function objects are created with functional literals:

// Creates a variable named add and store a function in it that adds two numbers:
var add = function(a, b) {
  return a + b;
}

A function literal has four parts.  The first parts is the reserved word function.  The
optional second part is the function's name.  The function can use its name to call
itself recursively.  The name can also be used by debuggers and development tools
to identify the function.  If a function is not given a name, it is said to be anonymous.

The third part is the set of parameters for the function, wrapped in parentheses.
Within the parentheses is a set of zero or more parameters names, separated by 
commas.  These names will be defined as variables in the function.

The fourth part is a set of statements wrapped in curly braces.  These statements are
the body of the function.  They are executed with the function is invoked.

A function literal can appear anywhere that an expression can appear.  Functions can
be defined inside of other functions.  An inner function of course has access to its 
parameters and variables.  An inner function also has access to the parameters and
variables of the outer function.  The function object created by a function literal
contains a link to that outer context.  This is called closure.

How can we define a function?

function functionName(p1, p2, p3) {
    statements;
}

Do we have to specify the number of parameters when we declare a function?

No. A javascript function can take 0 or more named parameters. The function body can declare its own variables which are local to that function. The named parameters turn out to be more like a guideline. You can call a function without passing the parameters it expects, in which case they will be set to undefined. You can also pass in more arguments than the function is expecting.

Can JavaScript function take any number of parameters?

Yes. A javascript function can take 0 or more named parameters. The function body can declare its own variables which are local to that function. The named parameters turn out to be more like a guideline. You can call a function without passing the parameters it expects, in which case they will be set to undefined. You can also pass in more arguments than the function is expecting.

What is the purpose of the arguments variable?

Functions also have access to an additional variable inside their body called arguments, which is an array-like object holding all the values passed to the functions. The arguments object is a local variable available within all functions. You can refer to a function's arguments within the function by using the arguments object. This object contains an entry for each argument passed to the function, the first entry's index starting at 0.

Can we manipulate the content of the arguments variable?

Yes. The arguments can also be set:

arguments[1] = 'new value';

Is the arguments variable a true array?

No. The arguments object is not an array. It is similar to an array, but does not have any array properties except length. For example, it does not have the pop method.

How can we convert the arguments variable into a real array?

var args = Array.prototype.slice.call(arguments);

How can we declare a function that takes arbitrary number of parameters?

In JavaScript, the list of parameters is optional. To examine the parameters that is actually passed, examine the arguments variable. The arguments variable is a special variable that is available in every function.

You can use the arguments object if you call a function with more arguments than it is formally declared to accept. This technique is useful for functions that can be passed a variable number of arguments. You can use arguments.length to determine the number of arguments passed to the function, and then process each argument by using the arguments object.

How can I determine the number of parameters that were declared as part of the function declaration?

To determine the number of arguments declared when a function was defined, use the Function.length property.

Can we assign a function to a variable?

Yes. Javascript lets you create anonymous function:

var avg = function() {
  // function body
}

This is extremely powerful as it lets you put a full function definition anywhere that you normally put an expression.

Can we call a function recursively?

Javascript allows you to call function recursively. This is particularly useful for dealing with tree structures. How can an anonymous function call itself recursively if they don't have a name? The answer lies with the arguments object, which in addition to acting as a list of arguments also provides a property called arguments.callee. This always refers to the current function, and hence can be used to make recursive calls:

var charsInBody = (function(elm) {
    if (elm.nodeType == 3) {
        // TEXT_NODE
        return elm.nodeValue.length;
    }
    var count = 0;
    for (var i = 0, child; child = elm.childNodes[i]; i++) {
        count += arguments.callee(child);
    }
    return count;
})(document.body);

How can we keep track of information between each function call using arguments.callee?

Since arguments.callee is the current function, and all the functions are objects, you can use arguments.callee to save information across multiple calls to the same functions. Here is a function that remembers how many times it has been called:

function counter() {
    if (!arguments.callee.count) {
         arguments.callee.count = 0;
    }
    return arguments.callee.counter++;
}

What is function overloading?

A common feature in other object-oriented languages, such as Java, is the ability to overload functions to perform different behaviors when different numbers or types of arguments are passed to them. While this ability isn't immediately available in JavaScript, a number of tools are provided that make this quest possible. Function overloading requires two things: the ability to determine how many arguments are provided, and the ability to determine the type of the arguments that are provided. Inside of every function in JavaScript, there exists a contextual variable named arguments that acts as a pseudo-array containing all the arguments passed into the function. It is not a true array (you cannot modify it, or call .push() to add new items), but you can access items in the array, and it does have .length property.

Does JavaScript have block scope?

In JavaScript, scope is kept within functions, but not within blocks. Perhaps, we can use closure to implement block scope if we really want to.

For browser-based JavaScript, all globally scoped variables are properties of which object?

For browser-based JavaScript, all globally scoped variables are actually just properties of the window object.

When a variable is not explicitly defined, what happens?

When a variable is not explicitly defined, it will become defined globally, even though it is only used inside a function.

How can function A call function B with the same argument list?

function b(){
}
function a(){
    b.apply(null, arguments);
}
a('fred', 'Sally', 'Jo');

Can we implement an anonymous recursive anonymous function?

Yes. arguments.callee allows anonymous functions to refer to themselves, which is necessary for recursive anonymous functions. A recursive function must be able to refer to itself. Typically, a function refers to itself by its name. However, an anonymous function does not have a name, and if there is no accessible variable referring to it, i.e. the function is not assigned to any variable, then how can a function invoke itself? This is where arguments.callee comes in. The following example defines a function, which, in turn, defines and returns a factorial function:

function makeFactorialFunc() {
   return function(x) {
      if (x <= 1)
         return 1;
      return x * arguments.callee(x - 1);
   };
}
var result = makeFactorialFunc()(5); // returns 120 (5 * 4 * 3 * 2 * 1)

Other interesting usages that I have not fully explore:

  1. combine arguments.callee with setTimeout, and closure
  2. combine arguments.callee with apply() in an object oriented environment

What is the scope chains and "scope"

The scope chain of the execution context for a function call is constructed by adding the execution context's Activation/Variable object to the front of the scope chain held in the function object's "scope" property. In ECMAScript, functions are objects. They are created during variable instantiation from function declarations, during the evaluation of function expressions or by invoking the Function constructor.

Function objects created with the Function constructor always have a "scope" property referring to a scope chain that only contains the global object.

Function objects created with function declaration or function expression have the scope chain of the execution context in which they are created assigned to their internal "scope" property.

In the simplest case of a global function declaration such as:

function exampleFunction(formalParameter) {
    ... // function body code
}

the corresponding function object is created during the variable instantiation for the global execution context. The global execution context has a scope chain consisting of only the global object. Thus the function object that is created and referred to by the property of the global object with the name "exampleFunction" is assigned an internal "scope" property referring to a scope chain containing only the global object.

A similar scope chain is assigned when a function expression is executed in the global context:

var exampleFuncRef = function() {
    ... // function body code
}

except in this case, a named property of the global object is created during variable instantiation for the global execution context but the function object is not created, and a reference to it assigned to the named property of the global object, until the assignment expression is evaluated. But the creation of the function object still happens in the global execution context so the "scope" property of the created function object still only contains the global object in the assigned scope chain.

Inner function declarations and expression result in function objects being created within the execution context of a function so they get more elaborate scope chains. Consider the following code, which defines a function with an inner function declaration and then executes the outer function:

function exampleOuterFunction(formalParameter) {
    function exampleInnerFunctionDec() {
        ... // inner function body
    }
    ... // the rest of the outer function body
}

exampleOuterFunction(5);

The function object corresponding with the outer function declaration is created during variable instantiation in the global execution context so its "scope" property contains the one item scope chain with only the global object in it.

When the global code executes the call to the exampleOuterFunction, a new execution context is created for that function call, and an Activation/Variable object along with it. The scope of that new execution context becomes the chain consisting of the new Activation object followed by the chain referred to by the outer function object's "scope" property (just the global object). Variable instantiation for that new execution context results in the creation of a function object that corresponds with the inner function definition and the "scope" property of that function object is assigned the value of the scope from the execution context in which it was created. A scope chains that contains the Activation object followed by the global object.

So far this is all automatic and controlled by the structure and execution of the source code. The scope chain of the execution context defines the scope property of the function object created, and the scope property of function object define the scope for their execution contexts (along with the corresponding Activation object).

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License