On Jul 9, 2007, at 9:09 PM, Kris Zyp wrote:
I think it seems worth considering what a programmer is intending
if writes
a function and defines a prototype for it. This is an explicit
action to
create objects that inherit from the prototype object. If a user has
specifically written code to inherit from c, wouldn't he expect to
inherit
everything from c, including fixtures and methods (that work, not
throw
incompatibility errors)?
Because it's possible to violate the type constraints on fixtures in
the non-subclass object created by the function constructor?
That seems like a real possibility. The class methods, unless
qualified by prototype, really do constrain the type of |this|, and
that's a big part of the value of classes. Consider the alternatives:
1. Classes do not constrain types, have to check everything that
might be different in a delegating object method call (|this|,
members) at runtime.
2. Delegate creation via (new F) given F.prototype = new C and class
C must make an instance of C, not of Object. This is not backward
compatible.
3. Delegating to class methods from an instance created via (new F)
somehow (how?) wraps the class methods with type-constraining
wrappers, so the cost is not born by the class methods when called
class instances.
I don't think any of these is a good plan.
If we access fixture properties and methods just as
we do do expando properties and functions, why wouldn't we expect
programmers to want and fixtures and methods to be inherited?
Because fixture means fixed, unlike expando or ad-hoc properties. If
you want to delegate without type constraints, you have the tools in
JS already. Using classes means either locking down fields and
methods, or (if you use dynamic and prototype qualifiers) emulating
the ES1-3 builtins and stuff like the DOM classes. In the former
case, you should get a type error. In the latter, you can do what you
say you want, but you have to write the class with extra qualifiers.
Defining
prototypes is not something that just automatically happens in
places, but
is a very intentional definition on the part of a programmer in
which they
want and expect inheritance.
So is defining a class.
So is mixing the two definitions, constructor function prototype (not
a definition but an assignment expression, of course) and class
definition.
And I still appeal to the symmetry and consistency of the is
operator
operating exactly the same as the old instanceof operator when the
testing
against a class:
(a is C) == C.prototype is in a's delegate chain (at least when
__proto__
has not been externally modified) that would be true with option 1.
The is operator tests whether its left operand is an instance of a
subtype (:, which is reflexive, so includes the type itself) of its
right operand. It is not instanceof, which tests whether its left
operand has a prototype equal to the value of the 'prototype'
property of its right operand (if that operand is an object). Don't
mention mutable __proto__ (it's a botch and irrelevant). Just consider:
function B() {}
function D() {}
D.prototype = new B
d1 = new D
assert(d1 is B) // false
assert(d1 instanceof B) // true
D.prototype = new Object
d2 = new D
assert(d2 is B) // false
assert(d2 instanceof B) // false
class B {}
class D extends B {}
d1 = new D
assert(d1 is B) // true
assert(d1 instanceof B) // true
D.prototype = new Object // silently fails because 'prototype'
// is DontDelete and ReadOnly in D
d2 = new D
assert(d2 is B) // still true
assert(d2 instanceof B) // still true
Not only can't you modify D.prototype, but (d1 is B) is true for
class B but false for function B.
You are right that is and instanceof agree in all four assertions for
classes. But only one of four corresponding assertions for
constructor functions is true. Classes are not functions, not by a
long shot.
/be
___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss