On 7/2/07 1:29 PM, Brendan Eich wrote:
> 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).
>>
This behavior is incorrect. For compatibility with ES3, property writes must
be shallow.
>>
>> 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).
>>
Agreed.
>>
>> 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.
>>
This seems a little too magic for me, and this is what classes are for. A
delegate (i.e. __proto__) is just a delegate whose static type is always
Object. If you want to benefit of type checking on instance properties, you
need to use classes, interfaces and/or structural object types to constrain
the instance.
>
> 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; }
>
To be clear, in the example above this would put a expando property x¹ on
f.__proto__.__proto__¹.
>
> 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.
>
See my comment before my last one. Making prototypes more like classes would
make them less flexible, more complicated, and duplicate functionality that
is already available. I don¹t see the point, but maybe I¹m missing the use
case.
Jd
> /be
>
>
> _______________________________________________
> Es4-discuss mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/es4-discuss
------ End of Forwarded Message
_______________________________________________
Es4-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es4-discuss