Output of the embedded scripts (use show source):
Note: on my browser the following line is "is half a loaf is better than 1" and
on the next line "truetruetrue".



Confounding Javascript with Python

by burt rosenberg

When writing webapps, one ends up writing Javascript and Python side by side. They are similar in syntax and things such as scoping, but then again, they have large differences. This page illustrates the the differences, to help in avoiding confusion among the two languages.

Dictionaries

In Python, dictionaries are a form of mapping type. They can be initialized using a sequence of comma separated name:value pairs, enclosed in curly braces. The are accessed using array notation involving square braces. The key can be any hashable, including numbers and strings.

In Javascript, a dictionary is the same as an object. It can be initialized using the same syntax as Python. The key can be a number, a string, or an identifier. Because the dictionary is also an object, the elements can be accessed either using array notation, e.g. b[i], or using property notation, e.g. b.i.

Consider an identifier used in an initializer, such as

     b = {i:j}
In Python both i and j are evaluated, but in Javascript, only j is evaluated. In Javascript you also have the privilege of writing in the dot notation, using the identifier i. Hence in Python,
     i='k'
     j=1
     b = {i:j}
     b['k'] -> 1
In Javascript,
     i='k'
     j=1
     b = {i:j}
     b['i'] // -> 1
     b.i // -> 1
     // b[i], b['k'] and b.k are not defined
In Javascript, using the identifier in dot notation is completely identical in all cases to using a string that "looks like" the identifier in array notation. Hence,
    b = { 'i':1 } ;
    b['i'] // -> 1 
    b.i // -> 1 
When a number or boolean is used in a dictionary, Javascript will access the element using a string representation of the number or boolean. Not so in Python — a string and a number (or boolean) are different hashables.


Javascript:
  
    z = 'f' ;
    var b = {4.5:'half a loaf ', 'i':'is ', z:"better than ", 1:1 } ; // a dictionary  
    document.write(b.i) ;  // can write b['i'] as b.i, but not b[i] nor b.'i'
    document.write(b['4.5']) ; // can write as b[4.5] also
    document.write(b['z']) ;  // can write b.z as b['z'], but not b[z]
    document.write(b[1]) ;   
    // document.write(b.1) ;   // error, doesn't parse
    // document.write(b[z]) ;  // error, z is not defined
    // document.write(b.'z') ; // error, says: missing name after . operator
    // document.write(b['f']) ;  // undefined. the z in the {} creation is not a variable
      
    document.write('<br>') ;
    a[true] = 'true' ;
    document.write(a[true]) ;
    document.write(a['true']) ;
    document.write(a[0==0]) ;
    
     b[4.5] = 4.5
     b['4.5'] = 5.4
     b[4.5] -> 5.4
     b['4.5'] -> 5.4

Python

     z = 'z' # else the next line fails
     one = 1 # a bit more about variables
     b = {4.5:'half a loaf ', 'i':'is ', z:"better than ", one:1 } ; # a dictionary  

     print b['i'], b[4.5], b['z'], b[1]
     
     b.i # error, dict object has no attribute i
     b.z # error, dict object has no attribute z
     b['1'] # error, no entry for '1'
     
     b[4.5] = 4.5
     b['4.5'] = 5.4
     b[4.5] -> 4.5
     b['4.5'] -> 5.4
     
     b[True] = 'true!'
     b[0==0] -> 'true!'
     b[0==1] = "false :-("
     b[False] -> 'false :=('
     

Scoping

Both Javascript and Python are dynamically scoped. Functions at the outer level either reference local variables, defined in a function, or global variables, defined at the file level. Inner functions might be passed as return values, and when this happens, the variables that function uses have to remain connected to the variables in scope at the time of function definition. Also, a stack of calls might reintroduce a variable at multiple levels.

Both Javascript and Python use the concept of a catalog, binding variable names to storage locations. A new catalog is created for each function scope entered. When a variable is defined, which means a function or def statement is encountered (not when the function is invoked! that would be another form of scoping!) the catalogs in effect are searched, from the most local towards the global catalog, looking for the variable name.

What matters is how variables get into the current open catalog. Javascript uses the a var statement to define a variable, placing it into the innermost catalog. Without var, the binding in the first catalog encountered with a binding for that variable will be used. As a word of caution, always use var, unless you are determined (against all advice) that the variable must be global — that is, is bound only in the default global catalog and all references to the variable will refer to the same data location. Often programmers add "_g" to the end of any such variable.

Note that Javascript scoping, using var, considers only global catalogs and local catalogs created by function execution. A var inside of a file or function places that variable in the catalog for the entire filre or function. This is called hoisting because it is as if the var statement were hoisted to the top of the page or function block. Beware however it is not exactly so, for in a statement such as var i = 0 the var i intent is hoisted, however the i = 0 intent remains in place.

Python will determine to binding of a variable in local scope according to use. If a variable is written into, it will forced into local scope, else the value will be take from the binding for the variable in the first enclosing catalog. Hence, this code works as planned:


    def fi():
        i=0
        def fo():
            return i
        return fo
            
    g = fi()
    g()  -> returns 0
    g()  -> returns 0

But this code causes a runtime error:


    def fi():
        i=0
        def fo():
            i = i+1
            return i
        return fo
        
    g = fi()
    g()  -> UnboundLocalError: local variable 'i' referenced before assignment

On the other hand, Javascript is not only happy with the following, it is pretty much how it is done (in this it follows Scheme):


function fo() { var i=0; return function(){ i=i+1; return i;}} // creates a closure in which lives i
fi = fo() ;
document.write(fi());  // writes 1
document.write(fi());  // writes 2
document.write(fi());  // writes 3
fj = fo() ;
document.write(fj());  // writes 1
document.write(fj());  // writes 2
document.write(fj());  // writes 3

As a practical matter, Python solves this sort of problem with an object:


class Fo():
    i = 0 
    def fi(self):
        self.i = self.i + 1
        return self.i

g = Fo()
g.fi() -> 0
g.fi() -> 1
h = Fo()
h.fi() -> 0

For the sake of completeness, this style is also supported by Javascript, e.g.:


function Fo() {
   return { i:0, fi: function() { this.i=this.i+1; return this.i; },
            __proto__:Fo.prototype }
   }

// N.B. The __proto__ property is not needed in this example, you could get rid of it
// for all that we are talking about now. However, Javascript inheritance would not work
// without it. The new operator is generally used to implement objects, and will set 
// __proto__ correctly.

g = Fo() ;
document.write(g.fi()) ;
document.write(g.fi()) ;
document.write(g.fi()) ;
// document.write(i); // error: Reference Error: i is not defined


which when run gives:

But see following for more about Javascript object syntax and semantics.

Objects

Python and Javascript differ fundamentally on objects. Python has class based inheritance and Javascript has prototype based inheritance. In Javascript, objects are the same as the dictionary data structure, so there is a magical "this" keyword to refer to the current dictionary. A function defined as a slot in the dictionary uses this to get at other slots in the dictionary. In Python, the reference to the instantiated object is passed explicitly as the first parameter of a method, and is by convention names "self".

Python allows multiple inheritance, Javascript does not.

Javascript objects can be created by: defining a hash with {} or an array with []; or using the functions Dict and Array; or by calling a function returning a hash; or by using the new operator. The new operator modifies the constructor syntax so that a dictionary is assumed to be the return value of the constructor.

In each of these instances, the constructor is an object (functions are objects), and they will copy the contents of their prototype field into the constructed object's __proto__ field. This defines the class of the object, in this sense: all objects foo forwhich foo.__proto__ == Foo.prototype are of class Foo. The prototype field is followed as a chain when resolving entries in the dictionary — if a name is not found in the object, it looks in the object of the object's prototype field, and so forth in prototype.prototype, etc.

The syntax for objects in Python and Javascript is demonstrated following. Also is demonstrated that each uses lazy bindings. In the "lazy binding" versions, when the functions fi are defined, i is not an attribute of the object. At the time of definition, the catalog in which i will be looked up eventually is fixed, but the catalog is not at that time searched. The fi functions return errors until and i slot is created.

Also, the Javascript syntax shown uses this and new. Elsewhere on this page (above) we have shown two other ways of creating an object, one which uses neither this nor new, and one which does not use new. The object can be created as a pure closure, and the binding rules substitute for the use of this; of the object can be created by a function returing a dictionary, and this generally is a self-reference to the dictionary. However, new also fills out the __proto__ slot properly, which is necessary for the prototyping mechanism to work properly.


Python:

    class Fo():
        i = 0 
        def fi(self):
            self.i = self.i + 1
            return self.i
    
    g = Fo()
    g.fi() -> 0
    g.fi() -> 1
    h = Fo()
    h.fi() -> 0
    
    class Fo_lazybind():
        def fi(self):
            self.i = self.i + 1
            return self.i
    
    g = Fo()
    g.fi() -> error Fo instance has no i attribute
    g.i = 0 
    g.fi() -> 1
    
Javascript:

    function Fo() {
       this.i = 0 ;
       this.fi = function () { this.i=this.i+1; return this.i; }
       }
    
    g = new Fo() ;
    document.write(g.fi()) ; // -->1
    document.write(g.fi()) ; // -->2
    document.write(g.fi()) ; // -->3
    
    // N.B. Use of the new operator simplifies object construction; else return
    // a hash with various magic slots initialized.
    
    function Fo_lazybind() {
       this.fi = function () { this.i=this.i+1; return this.i; }
       }
    
    g = new Fo_lazybind() ;
    document.write(g.fi()) ; // --> NaN
    g.i = 0 ;
    document.write(g.fi()) ; // -->1
    document.write(g.fi()) ; // -->2
    document.write(g.fi()) ; // -->3


Inheritance in Javascript

Javascript inheritance is by prototypes. Each object contains a reference to a super object. This property can be re-written to dynamically change the inheritance. Also, what is inherited is an object, not a template. Therefore changes to the super object propagate immediately to all subobjects. However, changes to an inherited attibute cause the attribute to be created in the inherting object. This is similar to Python's scoping rule, which will look for readable objects in a chain of dictionaries, but will insert writable objects into the local dictionary.

Javascript shadows inherited properties. Properties are inherited by following the chain of references found in the object's __proto__ slot. One object can inherit from another by inserting the inherited object as the value of the inheriting object's __proto__ slot. If an attribute is referenced for a get, the name will be searched for in "this", then "this.__proto__", then "this.__proto__.__proto__", and so on. For a put, a slot will be created in the this object. From then on, gets will refer to the new slot, unless __proto__ is specifically asked for.

This is similar to Java's "shadowing" of instance variables. In Java, instance variables are shadowed but instance methods are overridden. It is out of scope to digress on this further than to say, in Javascript, the mechanism is shadowing.

Basic examples


// see output for this script to the right -------------->

a = {i:1} ;
b = { j:2, __proto__:a } ;
c = { j:2, __proto__:a } ;
d = { j:2, __proto__:a } ;

function wa() {
    document.write('<p>a.i:'+a.i);
    document.write(' b.i:'+b.i);
    document.write(' c.i:'+c.i);
    document.write(' d.i:'+d.i);
}

document.write('<font color="green">Output from script:</font>') ;
wa() ;
a.i = 3 ; wa() ; // propagates
d.i = 4 ; wa() ; // shadows
d.__proto__.i = 5 ; wa() ;  // shadowing, exemplified
c.__proto__ = {i:6} ; wa() ; // dynamic prototypes

Standard usage examples

Use of the new operator automates certain step up for an object. By invoking the constructor with the new operator, a dictionary will be created, and "this" will be set in the function body to refer to that object. The function will set instance variable with this.i, for i a variable, and instance methods with this.f where f is a function. Typically, anonymous function syntax will be used such as this.f = function() { /* stuff */ } .

Furthermore, the prototype property of the constructor function will be copied into the __proto__ slot of the created dictionary, causing inheritance. Finally, the constructor attribute of the object will be set to the function object that constructed the object. This creates a vague way of considering class: objects are in the same class if they were constructed by the same constructor. However, since dictionaries are all very dynamic, this relationship might me little. Since the constructor slot, the prototype slot and the __proto__ slot can all be overwritten, implications about their values might be misleading.


// see output for this script to the right -------------->

document.write('<font color="green">Output from script:</font>') ;

function Q() { this.i = 1 ; } 
q = new Q() ;

document.write('<p>Q.prototype: '+Q.prototype) ;  // default prototype for a function is Object
document.write('<p>q isa Q:? '+(q.constructor == Q )) ; // was object q constructed from function Q


function R() { this.j = 3 ; }
R.prototype = new Q() ; // setting inheritance. note need instance
r = new R() ;

document.write('<p>r isa R?: '+(r.constructor==R)) ;  // type is R (i.e. constructed by R)
document.write('<p>r extends what R extends?: '+(r.__proto__== R.prototype)) ;  // extends what R extends
document.write('<p>r extends Q?: '+(r.__proto__.constructor==Q)) ; // .. inherits from Q.prototype

document.write('<p>r.j: '+r.j) ; // an instance variable
document.write('<p>r.i: '+r.i) ; // an inherited variable

r.i = 2 ;
document.write('<p>r.i: '+r.i) ; // i is shadowing __proto__.i
document.write('<p>r.__proto__i: '+r.__proto__.i) ;  // the shadowed variable


Lists

In Javascript, an array is a list. In Python there are no arrays, but there are Sequence types, and a list is a sequence type. To be continued ...


Copyright 2012 burton rosenberg
Last modified: 9 feb 2013