view source/objects.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

Objects
=======

JavaScript and Python have rather different object models and here we
give a broad view of the differences.  The simplest way to create a
JavaScript object ``jso`` is to write:

.. code-block:: javascript

   jso = {}


The closest builtin equivalent to jso in Python is the dictionary such
as **pyo**, which is created using:

.. code-block:: python
  
   pyo = {}


The two objects jso and pyo have important similarities and
differences (mostly differences).


Late news
---------

Not incorporated in this document is a recent discovery, that 

    **JavaScript objects are like Python classes with custom item
    methods (on the metaclass) that are never instantiated.**

I've put this material in a page on :doc:`javascript-objects`.


Similarities
------------

Both objects can be used to store data.  Here's a lightly edited
command line session (using the SpiderMonkey JavaScript interpreter):

.. code-block:: javascript

   js> jso = {}
   js> jso['A'] = 'apple'
   js> jso['A']
   apple


Here's the corresponding Python session (with *sys.ps1='py> '*):

.. code-block:: python

   py> pyo = {}
   py> pyo['A'] = 'apple'
   py> pyo['A']
   'apple'

In the examples above ``'A'`` is the key and ``'apple'`` is the value.
In both cases we are able to store values against keys.  In both cases
the value can be any object.  In most other respects, ``jso`` and ``pyo`` are
different.

Differences
-----------

Keys
^^^^

In JavaScript all keys are converted to strings.

.. code-block:: javascript

   js> jso = {}
   js> jso['1'] = 'one'
   js> jso[1]
   one

Here's an even more surprising example:

.. code-block:: javascript

   js> jso = {}
   js> a = {} ; b = {};
   js> jso[a] = 'apple'
   apple
   js> jso[b]
   apple


What's going on here?  Well, objects ``a`` and ``b`` are converted to
strings, and they have the same string representation, namely *'[object
Object]'*.  (We'll see later how we can change this.)  So let's try
this out (continuing the previous example):

.. code-block:: javascript

   js> jso['[object Object]']
   apple

Here, for comparison, is what happens with Python:

.. code-block:: python

   py> pyo = {}
   py> pyo['1'] = 'one'
   py> pyo[1]
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   KeyError: 1
   py> a = {}; b = {}
   py> pyo[a] = 'apple'
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: unhashable type: 'dict'



Here JavaScript, faced with input of the wrong type, has converted it
to the required type, which is a string.

.. note::

   In JavaScript anything can be a key, and all keys are converted to
   strings before lookup.  In Python, keys are unchanged, and have to
   be hashable.

.. note::

   Python built-in objects throw an error when given incorrect input.
   JavaScript converts the input to something that might work.

.. _object-missing-keys:

Missing keys
^^^^^^^^^^^^
The notation ``a[b]`` is called **indexing**.  In Python, indexing with
a key that is not present in the dictionary raises an exception.

.. code-block:: python

   py> pyo = {}
   py> pyo['dne']
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   KeyError: 'dne'


In JavaScript, we get *undefined*, which is a special JavaScript
object (which is diferent from the *null* JavaScript object).

.. code-block:: javascript
   
   js> jso = {}
   [object Object]
   js> jso['dne']
   js> jso['dne'] === undefined
   true

(SpiderMonkey does not echo *undefined* at the command prompt, just as
Python does not echo *None*.  Therefore we use equality to show that
we truly get undefined.)

.. note::

   In JavaScript you won't get a KeyError (or IndexError).  Instead,
   you get **undefined**.

In practice, JavaScript left to itself rarely throws an error.  It
most commonly happens with code such as

.. code-block: javascript
   
   obj_a.method(args)
   obj_b.name

where respectively ``obj_a.method`` and ``obj_name`` are undefined.


Attributes
^^^^^^^^^^

In JavaScript an object has a single set of properties, which can be
accessed both by indexing and as attributes.  Here is an example:

.. code-block:: javascript

   js> jso = {}
   js> jso['a'] = 'apple'
   js> jso.a
   apple
   js> jso.b = 'banana'
   banana
   js> jso['b']
   banana

In Python a dictionary has a set of key-value pairs and in addition it
has dictionary attributes, which are methods.


.. note::

   In JavaScript the three statements below are completely equivalent
   (except for assignment to ``tmp`` as a side effect).

   .. code-block:: javascript

      x = a.b
      x = a['b']
      tmp = 'b'; x = a[tmp]
      
   In addition, when ``a.b`` is a function then
 
   .. code-block:: javascript

      x = a.b(arg1, arg2, arg3)
      tmp = 'b'; x = a[tmp](arg1, arg2, arg3)

   are equivalent.
        
   But note also that 

   .. code-block:: javascript

      x = a.b(arg1, arg2, arg3)
      tmp = a.b; x = tmp(arg1, arg2, arg3
     
   are sometimes completely different.