On Mar 24, 2012, at 7:28 AM, David Herman wrote:
> On Mar 21, 2012, at 9:13 AM, Allen Wirfs-Brock wrote:
>
>> On Mar 20, 2012, at 11:32 PM, David Herman wrote:
>>
>>> Well, hang on now. The 'constructor' syntax is not "just the constructor
>>> property." It still carries special status; the semantics of a class says
>>> "look for the property called 'constructor' and make that the [[Call]] and
>>> [[Construct]] behavior of the class."
>>
>> Actually, the semantics is probably more like: the value bound to the
>> <classMame> is the function object defined by the <methodDefinition> whose
>> <propertyName> is "constructor".
>
> Yes, sure. Doesn't change the point: 'constructor' is still a special,
> distinguished method.
Yes it is. I think the core issue WRT to identifying this distinguished method
with an identifier other than "constructor" concerns how it would relate to an
actual method named "constructor".
The conservative course is to use "constructor" as the distinguishing
identifier. It is a direct reflection of the underlying ES<=5.1 chapter 13
and15 "class" model and it doesn't introduce any of these name naming issues.
I primarily favor sticking with "constructor" because the
safety/maximally-miminal proposal is all about being conservative...
> ...
>>> The question is how we spell that. This is 99.9% a surface syntax question.
>>> Tou could argue that spelling it 'new' should define a ["new"] method, or a
>>> ["new"] method and a ["constructor"] method, or just a ["constructor"]
>>> method. If the latter, it's semantically *identical* to spelling it
>>> 'constructor'. But even if we chose one of the other two alternatives, the
>>> semantic differences here are minor, and the ergonomics of the syntax
>>> matter.
>>
>> You need to drop the [ ]'s (although I'm not sure what you meant by them...
>
> I meant that there is a property of the prototype that you can access via
> either p["new"] or p["constructor"] or both, depending on which semantics we
> decide to give. No matter what the surface syntax, any of those semantics is
> available to us. I say:
>
> a) spell it "new" -- ergonomics trumps corner cases; hard cases make bad
> law
deviates from chapters 13 and 15.
(class () {}) isn't interchangeable with (function () {}). Shouldn't it be?
>
> b) desugar it to the constructor function and the p.constructor property
> only
but presumably means that an instance method named new can't be defined using a
class definition. Or, perhaps only if "new" is explicitly string quoted as a
property name. "new" is not a totally unreasonable method name. Also
presumably means that defining an instance method named constructor is
disallowed.
>
> c) i.e., don't create a p.new property -- no more prototype pollution
> please
I presume you mean it also doesn't define a p.constructor property. This has
similar problems to a). It deviates from the legacy ES "class model"
Also, most instance inherit from Object.prototype so they will still have an
inherited "constructor" property whose value is Object.
>
> d) an explicit 'constructor' method overrides the implicit creation of
> the 'constructor' method but does not define the constructor function
>
> Why d)? Remember, the .constructor idiom is a *very weak* idiom that many JS
> programs don't follow. If a JS program has some reason to use 'constructor'
> for a different purpose, trust them.
I believe the constructor idiom is most commonly not followed today when the
prototype property of a function is set to a new object (perhaps defined using
an object literal) and correctly dynamically setting the "constructor" property
is an extra step that is easily forgotten (an usually as no ill-effects)
However, with syntactic class definition support (including inheritance) in the
language I am sure that we are going to see much more use of OO idioms in ES
programs (if that wasn't the case why would be add them). A very common idiom
is to query the "class" of an object. Just look how frequently you see could
like p.class in Java or Ruby code or( p class) in Smalltalk code. Thew
equivalent of this using ES chapter 13/`5 objects is p.constructor. Which
would you prefer to see in future ES code p.constructor===q.constructor or
p.new===q.new
BTW, many OO experts including myself, tell people that querying the class of
an object in this manner is an undesirable practice. Maybe even an
anti-pattern. But in reality it is widely done and the negatives all relate to
non-fucctional issues like code flexibility and reusability. Developer are
going to do it, probably a lot.
>
>>>> Personally I think the answer should be "A" which implies that we have
>>>> class-side inheritance. This is a departure from current practice but
>>>> because "classes are functions" there is no way in ES<=5.1 to set up
>>>> class side inheritance other than by mutating __proto__.
>>>
>>> I always found this the more appealing, but then again, if I'm supposed to
>>> be going with the opposite of my instincts (see above), then maybe I should
>>> disagree with you. ;)
>>
>> I would guess that your instinctive response comes from thinking about a
>> "class" is something more than just a composite of objects. We can talk
>> more about this later after I respond to Mark
>
> I think you misread me. My instinctive response agrees with yours, not Mark's.
>
>> If the value of SOMEEXPRESSION is a constructor function (typeof ==
>> "function" && and has a "prototype" property) then the new constructor
>> inherits from SOMEEXPRESSION and the new prototype inherits from
>> SOMEEXPRESSION.prototype. Otherwise, the new consructor inherits from
>> Function.prototype and the new prototype inherits from SOMEEXPRESSION. That
>> is essentially the semantics I've defined for
>> SOMEEXPRESSION <| function () {}
Oops, the above isn't at all a correct statement of the current semantics of
SOMEEXPRESSION <| function () {}. My bad! In particular the "otherwise" clause
above is not that of <|.
I think it is best if I address the inheritance rules is a separate message
instead of burying it here.
>
> I'm not happy with that semantics, for either classes or <| (I believe others
> have objected on the list to the special-case semantics for <| as well).
> Since functions are objects, you can pass functions into contexts that expect
> an object and those contexts don't need to care whether the object they have
> is a function or an object. So this will lead to WTFjs moments where people
> take an object they got passed in from someone else and create a class with
> it, and it won't be wired up right because they didn't realize the object was
> a function.
>
> This kind of special-case ad hoc type testing in the semantics has a bad
> smell. It reminds me of stuff like the Array constructor that special-cases
> the number argument.
>
>> B = do{
>> let B = SOMEEXPRESSION <| function B(...) { ...};
>> B.prototype= SOMEEXPRESSION.prototype <| {constructor: B, ...}
>> B
>> }
>>
>> (or to be maximally explicit}
>>
>> B= do {
>> let B = function B(...) {...};
>> if (typeof SOMEEXPRESSION == "function" && typeof
>> SOMEEXPRESSION.prototype == "object") B.__proto__=SOMEEXPRESSION;
>> B.prototype= SOMEEXPRESSION.prototype <| {constructor: B, ...}
>> B
>> }
>
> Nit: you'd need to bind the result of SOMEEXPRESSION to a temporary, to avoid
> duplicating side effects. </macrology nerd>
>
> Dave
>
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss