view source/functions.rst @ 213:0ea90a1819c2 default tip

Custom theming
author Radomir Dopieralski <radomir.dopieralski@allegro.pl>
date Wed, 27 Jun 2012 16:35:54 +0200
parents 4e6cfa066d1a
children
line wrap: on
line source

Functions
=========

A function contains code, possibly with parameters, that is stored for
later use.  In both JavaScript and Python, functions are first-class
objects.  This means that identifiers can have a function as their
value, and be used as the parameter or return value of a function.

It's common, when writing JavaScript for web pages, to create a large
number of anonymous (nameless) and similar event-handing functions,
one for each node.  Often, :doc:`delegation` allows us replace a many
similar functions by a single function.

Defining a function
-------------------

When defining a function in JavaScript use

.. code-block:: javascript

   var my_fn = function(arg1, arg2, arg3){
       //  Body of the function.
   };

as the template, where of course you get to choose the number and
names of the parameters.  Unlike Python, you can't provide default
values for the arguments, nor can you provide ``*args`` and
``**kwargs``.  However, as we will see, there is the pseudo-variable
``arguments`` in JavaScript.

This template can be adapted

.. code-block:: javascript

   obj.my_fn = function(arg1, arg2, arg3){
       //  Body of the function.
   };

to define an attribute or method of an object.  This is most commonly
done when ``obj`` is a prototype.

You can also put a function in an object literal, as in 

.. code-block:: javascript

   obj = {
   
       'my_fn': function(arg1, arg2, arg3){
       //  Body of the function.
       }
   };

but this is often best avoided.  

JavaScript provides another method (called function declaration)

.. code-block:: javascript

   function my_fn(arg1, arg2, arg3){
       //  Body of the function.
   };

which should (in the author's view) never be used.  It has strange
properties [link].


.. _calling-a-function:

Calling a function
------------------

There are four ways of calling a function in JavaScript.  The
difference involves :doc:`functions-and-this`, which we've not covered
yet. In brief, the four forms are:

.. code-block:: javascript

   x = my_fn(a, b, c);                // Simple function call.
   x = obj.my_fn(a, b, c);            // Method  call.
   x = my_fn.call(obj, a, b, c);      // Explicit this call.
   x = my_fn.apply(obj, [a, b, c]);   // Explicit this apply. 

For all forms of the function call, supplying the wrong number of
arguments **does not raise an error**.  Instead, excess arguments are
ignored, and excess parameters are initialised to *undefined*.


Function call
^^^^^^^^^^^^^

This is the simplest form of function call.

.. code-block:: javascript

   x  = my_fn(a, b, c);

The this-object is set to the :doc:`global-object`, which causes a
problem only if the body of the function refers to ``this``.  Many
functions are intended to be used in this way.


Method call
^^^^^^^^^^^

This is the usual, but not the most general, way of setting the this-object.

.. code-block:: javascript

   x  = obj.my_fn(a, b, c);       // Usual form.
   x  = obj['my_fn'](a, b, c);    // Variant form.

The two forms are completely equivalent.  The ``this``-object is set to
the ``obj``.

The two following calls are always equivalent:

.. code-block:: javascript

   x  = a.b.c.d.e.my_fn(a, b, c);
   tmp = a.b.c.d.e
   x  = tmp.my_fn(a, b, c);

Method call gotcha
^^^^^^^^^^^^^^^^^^

In JavaScript the two following calls are rarely equivalent:

.. code-block:: javascript

   x  = obj.my_fn(a, b, c);
   tmp = obj.my_fn
   x  = tmp(a, b, c);

whereas in Python they always are.

For JavaScript, in the first the ``this``-object is ``obj`` while in the
second it is the global-object.  For explanation see [link].

Explicit this-call
^^^^^^^^^^^^^^^^^^

Suppose ``obj`` is a JavaScript object.  Then

.. code-block:: javascript

   x = my_fn.call(obj, a, b, c);

is equivalent to 

.. code-block:: javascript

   x = my_fn(a, b, c);

except that the ``this``-object is set to ``obj`` (rather than the global
object).  For more see [link].

Explicit this-apply
^^^^^^^^^^^^^^^^^^^

Suppose ``obj`` is a JavaScript object.  Then

.. code-block:: javascript

   x = my_fn.apply(obj, [a, b, c]);

is equivalent to 

.. code-block:: javascript

   x = my_fn(a, b, c);

except that the ``this``-object is set to ``obj``.  For more see [link].

Explicit this gotcha
^^^^^^^^^^^^^^^^^^^^

If ``obj`` is not a JavaScript object then in 

.. code-block:: javascript

   x = my_fn.call(obj, a, b, c);
   x = my_fn.apply(obj, [a, b, c]);

the ``this``-object is set to the global object (which is probably not
what you want).  For more see [link].