view source/classes.rst @ 162:77e87f1b5811 core-javascript

$ hg merge core-javascript.closure-exercises # done, at least for now
author jf3243
date Wed, 09 Nov 2011 17:00:38 +0000
parents ed7dd56152f7
children
line wrap: on
line source

Classes
=======

In Python, *class* is a language primitive.  JavaScript has no
built-in concept of class.  Therefore, if we are to have classes in
JavaScript then we (or some library) must implement them.  Here we
give an outline implementation of classes in JavaScript, so that the
basic language features can be understood.

:ref:`Recall <inheritance-tree>` that each object has a parent, which
in turn has a parent, all the way up to the root object (which has no
parent).  In Python (and other languages), classes are a way for
instances to share data and methods.  As a first approximation, let us
say *two objects belong to the same class if they have the same
parent*.

As well as sharing class data, each instance of a class has its own
data, which is added to the instance as part of its creation.  In
Python, this is usually done using the __init__ method (although
sometimes __new__ is also used).

Point in Python
---------------

In Python we might write:

.. code-block:: python

   class Point(object):

       def __init__(self, x, y):
           self.x = x
           self.y = y

       def move(self, dx, dy):
          '''Move point by changes dx and dy.'''
           self.x += dx
           self.y += dy

   mypoint = Point(2, 3)
   mypoint.move(1, 1)


Point in JavaScript
--------------------

To implement a similar class in JavaScript we need a function Point
that returns a point, and an object that is a parent for all the
points created by the Point function.  In Python we had a single
object, namely the class Point, that performed both roles.  In
JavaScript we need a constructor function and a parent object.


Parent object
^^^^^^^^^^^^^

We'll start with the parent object:

.. code-block:: javascript

   var base = {};               // Grandparent for all instances.
   var point = create(base);    // Parent to all points.

   point.__init__ = function(x, y){
       this.x = x;
       this.y = y;
   };

   point.move = function(dx, dy){
       this.x += dx;
       this.y += dy;
   };

See [link] for why we use this rather than self.


Constructor
^^^^^^^^^^^

We also need a constructor function

.. code-block:: javascript

   var Point = function(x, y){

       var instance = create(point);
       instance.__init__(x, y);
       return instance;
   };


In production we would use *arguments* and *apply* rather than
directly calling *__init__*.  Do you know why?

Advanced features
-----------------

This can be omitted at a first reading.

Improved toString
^^^^^^^^^^^^^^^^^

In Python we have, for example:

.. code-block:: python

   py> from point import Point
   py> Point(2, 3)
   <point.Point object at 0x20ead90>

We can get something similar in JavaScript by writing:

.. code-block:: javascript

   point.__classname__ = 'Point';
   base.toString = function(){
       return '<' + this.__classname__ + ' object>'
   };

Constructor factory
^^^^^^^^^^^^^^^^^^^

Here is a factory function for producing constructor functions,
such as Point above.

.. code-block:: javascript

   var constructor_factory(parent){
       return function(){
           var instance = create(parent);
           instance.__init__.apply(instance, arguments);
           return instance;
       };
   };

   var Point = constructor_factory(point);