This is a note to illustrate a style of data abstraction that is convenient in ActionScript and JavaScript, and possibly a few other languages. We abstract data to protect it and thus support an adversarial relationship between a routine and its caller.

The demo code runs in your browser. Rather than put the code in this html file twice I assume that you are using a browser that easily shows the html source of the current page, which includes the JavaScript source. The yields of these code fragments are computed by your browser and rendered in this browser window thus: {your yield | my yield}.

In the following “object” is always used in the sense of JavaScript—merely a mutable map from strings to values.

A Toy Task

We have 32 lights to turn on and off. We need to divide the authority to turn lights on from that to turn them off. The function grp in the head of this html page takes an initial setting for 32 lights and returns a (JavaScript style) object with just three properties: on, off and observe. Each of these three is a function. on(1<<3 | 1<<6) turns lights 3 and 6 on. off(1<<6) turns light 6 off. observe() returns the number whose binary bits indicate which lights are now on.

We make a new instance { |[object Object]} g. The lights are all out: {|0}. We turn on lights 3 and 6 then observe: {|72}. We turn off light 6 and then: {|8}.

I have two contractors ON and OFF. I trust ON to turn lights on and OFF to turn them off. They are each a function taking as an argument another function which provides to them the tool they need to do their job. I do ON(g.on) and OFF(g.off) which grants each of them just the authority it needs. If var g = grp(0); ON(g.on); OFF(g.off); g.observe(); yields 4, then I can be sure that ON turned that bit on. This conclusion does not involve examining the code of OFF.

JavaScript veterans will find the expression g.on(4) familiar but it is a different construction than is taught in most JavaScript tutorials where the practice is for on’s code to refer to this to get the instance variables. Writing g.on(4) delivers the object g to the body of the on function as the value of this. Our code for on does not need or refer to this. The conventional JavaScript constructor for grp might look something like Cgrp also in the head of the source of this file. Note that it is not necessary to nest functions in the conventional style for there is no reference to outer variables from within the nested functions. This gives similar results: {|72}. There is a vital difference: The code OFF(Cg.off) fails for a function is delivered to OFF which lacks access to the cell with the 32 bits. If OFF is coded
function OFF(f){f(1<<3);}
the conventional body of off defined in Cgrp finds that its value of this is null: {|72}; (72 = 1<<6 | 1<<3) Bit 3 is still on! If the interface to OFF were changed to take Cg instead of Cg.off then we would have to look at the code for OFF to be sure that it did not turn on bits.

Dual Concept of an Expression’s Value

This mystery is due to an obscure but vital feature of JavaScript: when: expression x.b(e,e) is evaluated thus: The value of x is delivered to the function body of b as the value for this along with the explicit arguments. x.b(e,e) is not the same as (x.b)(e,e). The expression (x.b)(e,e) will fail if the body of b refers to this for there is no this there. This confusing situation is described in the official language definition thus: There are two concepts of “the value of an expression”. The “type Reference” value of an x.b is computed by the implementation and retains knowledge of x as well as b. That extra knowledge of x is lost in contexts of x.b such as (x.b) and v = x.b but it is specifically available in x.b(e,e) where it is passed to the body of b as this. This concept is sort of like C’s “l-value”.

Perhaps the Pizza superset of Java gains this advantage.

In jargon introduced elsewhere, g.off and g.on are facets of g.

These two styles can be mixed so that instance variables stored in the base object are public, in the sense of Java, while instance variables in the closure are private in the sense of Java.

There is a new language feature in JavaScript which explicitly provides classes more like C++ and Java. I do not know how that abstracts data.

As a post-script I show that two banks of lights can be instantiated. We left bank g with just light 3 on: {|8}. We make a new bank, g2, with lights 0 thru 3 on: {|15}. The first bank is unaffected: {|8}.

Daved Hopwood points out a pit-fall in this and I counter with further observations.