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.
>> Regardless of whether we spell it 'constructor' or 'new' it requires special
>> semantics that says "there's one distinguished method form in the body that
>> determines the constructor of the class."
>
> There is one distinguished method that is the class object (aka, the
> constructor function). A class declaration essentially desugars into the
> definition of a constructor function and a object that is the prototype
> associated with that constructor.
Again, doesn't change the point: whether you spell it 'new' or 'constructor'
it's still a distinguished method, and then you can desugar that however you
want.
>> 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
b) desugar it to the constructor function and the p.constructor property
only
c) i.e., don't create a p.new property -- no more prototype pollution please
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.
>>> 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 () {}
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