1. Jonathan Fine
  2. javascript-for-python-programmers


Jonathan Fine  committed 5bec62c

counters-discuss.rst: Added editorial changes and some additional content.

  • Participants
  • Parent commits 660cb65
  • Branches default

Comments (0)

Files changed (2)

File source/counters-discuss.rst

View file
-Counters example
+Counters discussion
-The goal is to create a web page which contains several independent
-counters.  Each time a counter is clicked, it is incremented.  Here's
-you can `try out a working example <./_downloads/counters.html>`_ of
-what's wanted.
+Here we go though the file *counter.js* broken into small pieces,
+explaining what's going on.
 We define and execute an anonymous function in order to create a
 private namespace.  Just like any other function, variables declared
 and used in the function are not accessible from outside, unless we
 explicitly provide access.  Returning a value is one way to do this.
+Adding an attribute to the global object, or something accessible from
+the global object, is another.
 .. literalinclude:: /examples/counters.js
    :language: javascript
 in JavaScript the *module pattern*.
 From one point of view, the *create* function should be, but is not, a
 built-in function in JavaScript.  Instead we have to create it
 The *create* function creates a new object whose parent in the
 inheritance tree is the *parent* argument.  What could be simpler than
+that?  The *create* function is similar to Python's *__new__*, in that
+it gives the class/parent of an object.
 The *new* operator has semantics such that the above code provides an
 implementation of *create*.  However, we don't for now need the
 somewhat complex semantics of *new*.
 Global object
 JavaScript has a global object, whereas Python does not. (Python's
 main module is similar but in many important ways different.)
         global.window = global;
 It is better to write *window* rather than *this*, but writing
-*global* for the global object is the best.  (Command line JavaScript
-interpreters don't start with *window* as the global object, and in
-the browser *window* has many special properties.)
+*global* for the global object is best of all.  (Command line
+JavaScript interpreters don't start with *window* as the global
+object, and in the browser *window* has many special properties.)
 Counter class
 Every class needs a prototype object.  We'll call it *counter*.  Don't
-confuse the *counter* prototype with *Counter* instance, which might
+confuse the *counter* prototype with a *Counter* instance, which might
 also be called *counter*.  Fortunately, in well organised code the
 prototype object of a class is in one namespace/module, and instances
 are in different namespaces.
 properties, together with those of *apply*, cause the JavaScript code
 above to have the same general effect as the Python code.
+(We won't sweat the details now.  Most of the time use of *call*,
+*apply*, *create* and *arguments* can and should be hidden behind the
+scenes.  But you need to know that this can be done so that when the
+time come, **you** can provide an efficient and elegant interface by
+using them to refactor complexity into something that is put behind
+the scenes.)
 The gist of the above code is that
    .. code-block:: python
 Counter properties
 The *__init__* method is called, of course, when a newly created child
 of the *counter* prototype needs to be initialised.  Each counter has
 This code is specific to a particular page or perhaps group of pages.
 It creates *Counter* instances (sensible, as we want to count) and
 This will do the job.  Notice the inelegant way in which we initialise
 the display of the counters.  Clearly this won't do if we're inserting
-say a slideshow into the page.
+say a slideshow into the page.  It's an exercise to write something
 .. literalinclude:: /examples/counters.js
    :language: javascript
 its ID, to a counter instance in the models array.  This was done on
-When a counter element is clicked we can, from its ID, find the
-correspond counter instance and, so to speak, click it.  We can also
-ask the counter instance to generate new HTML for the refreshing of
-the counter element.
+When a counter element on the page is clicked we can, from its ID,
+find the correspond counter instance in the models and, so to speak,
+click it.  We can also ask the counter instance to generate new HTML
+for the refreshing of the counter element.
 In short, everything has been set up to make delegation as easy as
 possible.  We'll assume that the generic function *onclick_factory*
-.. literalinclude:: /examples/counters.js
-   :language: javascript
-   :lines: 61-78
-Closing namespace
+In an ideal production environment this code would come from a
+well-supported standard library.  However, we're not there yet.
+The *onclick_factory* is an example of a closure.  The returned
+function has a hidden reference to the models argument that is passed
+to the *onclick_factory*.  Each execution of *onclick_factory* refers
+to the *models* argument that was passed to it.
 .. literalinclude:: /examples/counters.js
    :language: javascript
-   :lines: 79-
+   :lines: 61-79
+Closing namespace
+.. literalinclude:: /examples/counters.js
+   :language: javascript
+   :lines: 80-
 This little piece of line noise does three things.  
 a framework.
 Garbage collection
 The JavaScript garbage collection deletes objects provide it can
 discover that they can never be used again.  The simplest case is:
 see, the execution context of the function continues.
 IE memory leaks
 Internet Explorer, prior to IE8 (check) had **two memory heaps**, one
 for JavaScript and the other for the DOM.  Each heap had its own
 The *example* DOM node continues to exist, as it can be reached from
 the *document* node.  It has an *onclick* attribute, which is the
 the execution context.
 Reclaiming memory
 Notice that the JavaScript holds only two reference to DOM nodes,
 namely *document* and *example*.  However, the line of code

File source/examples/counters.js

View file
     var onclick_factory = function(models){
         var onclick = function(event){
 	    event = event || global.event; // For IE event handling.
 	    var target = event.target || event.srcElement;
             var id = target.id;
             if (id) {
-                var id_num = id.slice(1);
+                var id_num = +id.slice(1);
                 var model = models[id_num];
-                var html = model.html();
+                var html = model.html(id);
                 if (html){
                     document.getElementById(id).innerHTML = html;