This seems to omit one feature of Javascript objects that can be efficient (as much as I'm aware of how such things are implemented)—something I sort of alluded to in my class proposal.
That is that JavaScript objects (essentially maps in the Rebolsphere) only contain a keylist for values that are different and keys common to a type of object are contained in the prototype's keylist (or the prototype's prototype all the way back to the Object object).
The implementation is a bit awkward requiring constructors and such, but I'll try and relate to the above (could use Object.create
but with caveats):
// first point of awkwardness, we generally need a function
// to create a prototype
//
let Point = function () {}
// now that we have this base, we can build the prototype
//
Object.assign(
Point.prototype, {
x: 0, y: 0,
form: function () {return this.x + 'x' + this.y}
// `this` in methods is not equiv. to Rebol's `self`
} // <= the prototype we really want
)
//
// Point.prototype has a keylist of [x, y, form]
//
// Create a new derivative object with a keylist of []
//
let point_1 = new Point()
console.log( point_1.x ) // => 0
// Let's expand the keylist to [x]
//
point_1.x = 1
// It still resolves `y` from the prototype
//
console.log( point_1.y ) // => 0
// And the method will work back through the
// prototype chain to resolve each key
//
console.log( point_1.form() ) // => '1x0'
// Creating another derivative object with a novel key
// does not alter the prototype or other inherited types
//
let point_2 = new Point()
point_2.z = 10
console.log( Point.prototype.z ) // => undefined
console.log( point_1.z ) // => undefined
// Keys added to the prototype are available to derivatives
//
Point.prototype.z = 100
console.log( point_1.z ) // => 100
Anyways, there's a few more interesting features related to this, but thought it worth adding the essential model to the mix.