delegating to typed objects

Brendan Eich brendan at mozilla.org
Mon Jul 2 13:29:46 PDT 2007


On Jul 2, 2007, at 9:21 AM, Kris Zyp wrote:

> It appears (at least in the reference implementation) that one  
> there is an object that has a delegate object that is a typed  
> object, that overwriting members in the top instance is sometimes  
> not possible. For example:
> class C { var x : String; }
> c = new C;
> function F() {}
> F.prototype=c;
> f = new F; // f.__proto__ = c
> f.x =4;
> If you do this c.x now equals "4", that is the value is not set in  
> f, but it goes up the prototype chain and sets 4 into x (and does  
> implicit conversion). I think I realize why this is being done. c  
> is of type C, but f is not of type C, but it still must maintain  
> consistency in the typing of its members (so instance method can be  
> assured of the right types, I presume). However, this seems that  
> like quite unintuitive behavior for JavaScript. Generally one would  
> expect the statement f.x=4; to only affect f, not f's delegate (c).  
> Was it ever considered to enforce a system where if f delegates to  
> c, that f must be the same type (or subtype) as c? This could be  
> done by allowing [[Class]] definition to be inheritable from a  
> delegate (in this f would not define what [[Class]] it is, but  
> would inherit it's class definition from c which defines it's class  
> to be C), and maintaining prototype chain consistency with class  
> inheritance.


If you want x to be a delegated and override-able "plain old"  
property, not a fixture, declare C thus:

class C { prototype var x : String; }

Without prototype qualifying var, you get a fixture, and fixtures are  
always fixed as to meaning and type constraint by type of their  
containing class. That's their raison d'être.

Having said that, I'll admit that your suggested change to the class  
instantiated by (new F) given F.prototype = new C is interesting and  
provocative. By default, ES4 as reference-implemented follows ES3 and  
makes (new F) for all functions F creates a new Object instance. But  
native constructor functions and classes can make instances of  
narrower types than Object, obviously (Date, RegExp, etc.). And some  
built-in classes (at least RegExp per ES3's spec, although no  
browsers follow this) have *prototype* properties of type Object.

So there's an attractive symmetry in making F.prototype = new C cause  
(new F) to instantiate C instances.

If we did this, you would still have fixtures overriding prototype  
properties, but you would have a fixture per (new F) instance, not  
one in the (new C) prototype instance as in your example (the one  
denoted by the variable |c|). That would avoid the pigeon-hole  
problem. (You could also use the prototype qualifier as in my counter- 
example.)

If we did this, you might also (or might not) want |dynamic| in front  
of class C {...} in order to allow "expandos".

Still thinking, comments welcome.

/be
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.mozilla.org/pipermail/es-discuss/attachments/20070702/697008bd/attachment-0002.html 


More information about the Es4-discuss mailing list