I now realized that I had a mistake in my mental model and that the
difference is smaller than I thought. Whatever LHS is, it always behaves
the same: it is set as a {[Prototype]] of the RHS. Putting RHS.prototype
into LHS.prototype is pure "addon". Seeing it this way, it is ok.
Even when it is only "addon", it is in fact different behaviour.
It would be nice if
x <| whatever-blueprint
could be defined so that object is created from whatever-blueprint and
its [[Prototype]] is set to x. Even if RHS is function expression (or
whatever in the future).
I'd suggest that setting parallel constructor/prototype hierarchy (very
nice thing which should definitely be in the language), should be
provided by different means. namely by class-specific keyword extends.
const Fox = function (...) extends Animal { ... } // expression
function Fox (...) extends Animal { ... } // declaration
This could kill two bird in one stone: <| could have consistent
prototypal semantics all over, and doing class-like double hierarchy
would be done with well-known class-domain keyword.
What do you think?
Herby Vojčík wrote:
> Hello,
>
> I now realized that I had a mistake in my mental model and that the
> difference is smaller than I thought. Whatever LHS is, it always behaves
> the same: it is set as a {[Prototype]] of the RHS. Putting RHS.prototype
> into LHS.prototype is pure "addon". Seeing it this way, it is ok.
Even when it is only "addon", it is in fact different behaviour.
It would be nice if
x <| whatever-blueprint
could be defined so that object is created from whatever-blueprint and
its [[Prototype]] is set to x. Even if RHS is function expression (or
whatever in the future).
I'd suggest that setting parallel constructor/prototype hierarchy (very
nice thing which should definitely be in the language), should be
provided by different means. namely by class-specific keyword extends.
const Fox = function (...) extends Animal { ... } // expression
function Fox (...) extends Animal { ... } // declaration
This could kill two bird in one stone: <| could have consistent
prototypal semantics all over, and doing class-like double hierarchy
would be done with well-known class-domain keyword.
What do you think?
Herby
>
> Allen Wirfs-Brock wrote:
>>
>> On Mar 4, 2012, at 1:59 PM, Herby Vojčík wrote:
>>
>>> Hello,
>>>
>>> I feel uneasy about this in <| proposal:
>>>
>>>> If the LHS operand has a property named prototype and the RHS
>>>> operand is a function expression then the [[Prototype]] of the
>>>> function object is set to the LHS object and the prototype property
>>>> of the new function is set to a new object whose [[Prototype]] is the
>>>> value of the LHS’s prototype property.
>>>
>>> It looks a little "perlish" to me, in the sense that when you write
>>>
>>> x <| function (...) {...}
>>>
>>> you must guard what x is because you can get two different outcomes
>>> (same as perl can use element in place of container, which backfires if
>>> the element itself is a container). I think it should be rephrased as:
>>>
>>>> If the RHS operand is a function expression then
>>>> a. if the LHS operand has a property named prototype the
>>>> [[Prototype]] of the function object is set to the LHS object and the
>>>> prototype property of the new function is set to a new object whose
>>>> [[Prototype]] is the value of the LHS’s prototype property.
>>>> b. otherwise TypeError exception is thrown.
>>>
>>> Herby
>>
>> Here[1] is a specific instance of how this feature is useful:
>>
>> //define a non constructible superclass that provides some
>> Smalltalk-like conventions
>> const AbstractClass = Function.prototype <| {
>> subclassResponsibility() {throw new Error(this.name+" did not
>> implemented an abstract method")},
>> shouldNotImplement() {throw new Error(this.name+" should not implemented
>> by "+this.name)},
>> name: "AbstractClass",
>> prototype: Object.prototype <|{
>> get class() {return this.constructor},
>> error(message) {throw new Error(message)},
>> subclassResponsibility() {return this.class.subclassResponsibility()},
>> shouldNotImplement() {return this.class.shouldNotImplement()},
>> errorSubscriptBounds(index) {this.error("subscript is out of bounds:
>> "+index)}
>> }
>> };
>>
>>
>> See the full js file for its use in context. But the basic idea is that
>> we need to set up the root of both the class-side and instance-side
>> inheritance chains. Your definition would make that impossible. This is
>> an unusual use-case but it does occur when working at the root
>> inheritance level. In addition to this specific example I think it will
>> be useful when languages that are compile to JS need to implement their
>> language-specific inheritance hierarchies while still exploiting the
>> mechanism provided by JS.
>>
>> I do want to intend to put some further though into the details of how
>> I've specified this, but I think it is a capability that we need.
>>
>> Allen
>>
>> [1]:
>> https://github.com/allenwb/ESnext-experiments/blob/master/ST80collections-exp1.js#L90
>>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
Herby Vojčík wrote:
Even when it is only "addon", it is in fact different behaviour. It would be nice if
x <| whatever-blueprint
could be defined so that object is created from whatever-blueprint and its [[Prototype]] is set to x. Even if RHS is function expression (or whatever in the future).
I'd suggest that setting parallel constructor/prototype hierarchy (very nice thing which should definitely be in the language), should be provided by different means. namely by class-specific keyword extends.
const Fox = function (...) extends Animal { ... } // expression
function Fox (...) extends Animal { ... } // declaration
This could kill two bird in one stone: <| could have consistent prototypal semantics all over, and doing class-like double hierarchy would be done with well-known class-domain keyword.
What do you think?