On Mar 20, 2012, at 6:59 PM, Allen Wirfs-Brock wrote:
> On Mar 20, 2012, at 11:55 AM, David Herman wrote:
>
>> The part that I'm least happy about is that this doesn't allow for
>> declarative private methods, because if we had the computed syntax like what
>> we're adding to object literals, it would clash with hoisting:
>
> We can live quite nicely with treating class declaration like const
> declarations. The name is logically hoisted so it is visible over the
> lexical scope, but the name is temporally dead until the class declaration is
> executed, in statement sequence, as an initializer. That means that we can
> have circular references between classes and forward references in inner
> functions to classes. The class declaration just need to be initialized
> before any such reference is actually evaluated. Its TDZ for classes.
>
> Practically, that means that super classes declarations have to appear in the
> text before subclasses and that you probably can't tuck all your class
> declaration at the end of the block/function (yuck, anyway) like you can with
> function declarations. I think we can live fine with that.
>
> Regarding privates, if classes are initialized in that manner there shouldn't
> be any problem with the pattern you use for in your example above. It works
> exactly the same as for object literals.
Y'know, I think I'm about sold. Somehow it just seemed obvious to me that
classes should be pre-initialized like functions. But just about every time
something seems obvious to me I'm wrong. I should learn to trust the opposite
of my instincts. ;)
Seriously, though, your argument for TDZ makes sense to me.
>> My only syntactic quibble: `constructor` is so inconveniently long. I've
>> argued in the past for `new` as special syntax in class bodies that
>> indicates a constructor.
>
> Well, it is defining the value of the constructor property. New syntax (eg,
> new) could always be added latter. I don't think we should risk derailing on
> it now.
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."
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." 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.
Look, it won't be the end of the world if we go with 'constructor'. This
particular question won't derail classes. But let's not tax the ergonomics for
what would be either a tiny or even non-existent semantic difference.
> So here is my one possibly future hostile (or we need to decide now) issue:
>
> class A {};
> A.classProperty="A";
> class B extends A {};
> Console.log(B.classProperty); //"A" or undefined??
>
> I don't believe Russell said, one way or the other. Potentially either way
> could be seen as future hostile if you think the "right" answer is the other
> one (and we have to do something in this regard).
Agreed; this is a decision we can't defer if we support `extends`.
> 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. ;)
Seriously, though, Mark's concerns are valid. (On a semi-related note, I intend
to try an alternative of the binary data API with no meta-classes.) We can work
through this issue.
> We could make an accommodation that this only occurs if the "superclass"
> object is a function. Otherwise, the "superclass" is only uses as the
> [[Prototype]] of the prototype and the constructor function simply inherits
> from Function prototype. BTW, I assume the thing the the right of extends
> is an expression.
>
> So, if you could say:
> class B extends A.prototype {}
>
> if you don't want the class-side inheritance
Wait, I don't see how that could work. If the RHS of `extends` is an arbitrary
expression, and we allow the programmer the freedom to provide either a
super-class or a super-prototype, how do we know what the prototype's prototype
is? IOW, it's ambiguous whether to treat:
class B extends SOMEEXPRESSION { ... }
as:
B = do {
function B(...) { ... }
B.prototype = SOMEEXPRESSION <| { ... }
B
}
or:
B = do {
function B(...) { ... }
B.prototype = SOMEEXPRESSION.prototype <| { ... }
B
}
Dave
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss