Avoiding overloading the term “prototype”
Axel Rauschmayer wrote:
This probably comes across as being overly obsessed with details, but I think that clear terminology matters. It would be nice if we could avoid the term “prototype” being overloaded in ECMAScript. It still trips up JS beginners: When I explained proto at JSConf, the first question was: “How is proto better than the ‘prototype’ property that all constructors already have?”
How about the following?
- proto (of an obj): the “fallback” object, access via proto
- prototype (of a type): value of Constr.prototype
Well, this bugged (and bugs) me long ago; that neither .prototype nor proto/[[Prototype]] is Prototype (GoF or Self way).
Beginners were always confused - I ended up calling [[Prototype]] "parent" or "ancestor" and .prototype "shared instance traits", "shared instance parent" or something like that (the term did not stabilize).
I would really glad, if the terms would be changed so that they will be truer, that is, none of those two things would be called proto(type). There is legacy reason why one is access via proto/Object.getPrototypeOf() and the second via .prototype, but it would be awesome if they get the names which really would grasp their real meaning.
I was just too scared to bring it on, because it seemed that this is set in stone.
I was just too scared to bring it on, because it seemed that this is set in stone.
The risk is that renaming increases the confusion instead of fixing it. And I had forgotten that we already have Object.getPrototypeOf(), but that should largely be replaced by proto in the future.
But I think it’s worth it to at least try to improve things. At the moment, it is difficult to talk about, without confusing people.
Herby Vojčík wrote:
Axel Rauschmayer wrote:
This probably comes across as being overly obsessed with details, but I think that clear terminology matters. It would be nice if we could avoid the term “prototype” being overloaded in ECMAScript. It still trips up JS beginners: When I explained proto at JSConf, the first question was: “How is proto better than the ‘prototype’ property that all constructors already have?”
How about the following?
- proto (of an obj): the “fallback” object, access via proto
- prototype (of a type): value of Constr.prototype
Well, this bugged (and bugs) me long ago; that neither .prototype nor proto/[[Prototype]] is Prototype (GoF or Self way).
Beginners were always confused - I ended up calling [[Prototype]] "parent" or "ancestor" and .prototype "shared instance traits", "shared instance parent" or something like that (the term did not stabilize).
I would really glad, if the terms would be changed so that they will be truer, that is, none of those two things would be called proto(type). There is legacy reason why one is access via proto/Object.getPrototypeOf() and the second via .prototype, but it would be awesome if they get the names which really would grasp their real meaning.
By the way, let deprecate (that is, recommend not to use) proto and introduce @parent (or other term) instead, while both having the same behaviour.
By the way, let deprecate (that is, recommend not to use) proto and introduce @parent (or other term) instead, while both having the same behaviour.
I'm not sure what to call it, but I think this would be much nicer than proto and consistent with the new way of doing things. Here are some ideas:
- @proto
- @extends
- @parent
- @prototype
- @prototypeOf
@prototypeOf seems a little silly as a property name, but it would work well with getPrototypeOf()
It wouldn’t fix the main problem with proto: using a property to express meta-data. In a way, proto might even be better than, say, @proto, because it will be the only property with double underscore, highlighting the specialness of that property.
On Twitter, @marcoos correctly commented that changing the name of [[Prototype]] (including prototypal inheritance, prototype chain, etc.) is too drastic an overhaul. Finding a better name for Constr.prototype seems easier.
Axel
On Monday, October 22, 2012 at 6:02 PM, Axel Rauschmayer wrote:
It wouldn’t fix the main problem with proto: using a property to express meta-data. In a way, proto might even be better than, say, @proto, because it will be the only property with double underscore, highlighting the specialness of that property.
On Twitter, @marcoos correctly commented that changing the name of [[Prototype]] (including prototypal inheritance, prototype chain, etc.) is too drastic an overhaul. Finding a better name for Constr.prototype seems easier.
I'd argue that even less experienced JS devs understand what the C.prototype is over the [[Prototype]].
Perhaps some kind of association with super?
Herby Vojčík wrote:
By the way, let deprecate (that is, recommend not to use) proto and introduce @parent (or other term) instead, while both having the same behaviour.
We could do this, given symbols, but would it help? New code could use it in the next several years only with an ES6->ES5 compiler and ignoring
IE on desktop; this is a real possibility for "mobile developers", self-defined. But developers could just as well use proto and probably will skip the compiler without strong need for other ES6 features.
This means we're adding a nicer synonym for the very long run. Which means two things, more total surface syntax, more "cruft" from certain points of view. Is it worth it?
Brendan Eich wrote:
Herby Vojčík wrote:
By the way, let deprecate (that is, recommend not to use) proto and introduce @parent (or other term) instead, while both having the same behaviour.
We could do this, given symbols, but would it help? New code could use it in the next several years only with an ES6->ES5 compiler and ignoring IE on desktop; this is a real possibility for "mobile developers", self-defined. But developers could just as well use proto and probably will skip the compiler without strong need for other ES6 features.
This means we're adding a nicer synonym for the very long run. Which means two things, more total surface syntax, more "cruft" from certain points of view. Is it worth it?
I think 'cruft' is too strong. There will be two things that do the same thing, one 'legacy', one new. Though I can not give an example, I have the impression things like that happens (use X, there is Y for compatibility, for it is not endorsed now...) often.
Having things in 'less than happy' state in more details simply breaks the (possible good) progress. At least my experience is, that if you refactor details of this kind (though they may seem formal), the 'flow' is freed. So if change of this kind is accompanied with terms cleaning as well, it may move the whole thing on to new quality.
But. I am not the one responsible, I do not see all the differing implications.
Axel Rauschmayer wrote:
It wouldn’t fix the main problem with proto: using a property to express meta-data. In a way, proto might even be better than, say, @proto, because it will be the only property with double underscore, highlighting the specialness of that property.
Isn't iterator similar? Array's length also is magical.
On Twitter, @marcoos correctly commented that changing the name of [[Prototype]] (including prototypal inheritance, prototype chain, etc.) is too drastic an overhaul. Finding a better name for Constr.prototype seems easier.
Well, Constr.prototype is the much nearer to obvious meaning of the word prototype than is [[Prototype]] (though "blueprint", "skeleton" etc. seems to be a little more appropriate, but the difference is not that big). Letting [[Prototype]] called prototype and renaming Constr.ptototype is against common logic (imho).
Prototypal inheritance is ok, since this is the term often used for classless, object-to-object inheritance (or, maybe just JS made them synonyms?).
But if only one should be renamed, I'd argue for [[Prototype]] (and so prototype chain would need to be renamed, too; to plain inheritance chain, for example (goes well with [[Parent]] as well as [[Ancestor]])).
Herby Vojčík wrote:
Brendan Eich wrote:
Herby Vojčík wrote:
By the way, let deprecate (that is, recommend not to use) proto and introduce @parent (or other term) instead, while both having the same behaviour.
We could do this, given symbols, but would it help? New code could use it in the next several years only with an ES6->ES5 compiler and ignoring IE on desktop; this is a real possibility for "mobile developers", self-defined. But developers could just as well use proto and probably will skip the compiler without strong need for other ES6 features.
This means we're adding a nicer synonym for the very long run. Which means two things, more total surface syntax, more "cruft" from certain points of view. Is it worth it?
I think 'cruft' is too strong. There will be two things that do the same thing, one 'legacy', one new. Though I can not give an example, I have the impression things like that happens (use X, there is Y for compatibility, for it is not endorsed now...) often.
Number.isNaN adds value, by not coercing non-number arguments to number, compared to isNaN. Ditto similar innovations, see brendaneich.com/2012/10/harmony-of-dreams-come-true near the bottom.
By contrast, @parent would be no better in function (ignore form) from proto.
Having things in 'less than happy' state in more details simply breaks the (possible good) progress. At least my experience is, that if you refactor details of this kind (though they may seem formal), the 'flow' is freed. So if change of this kind is accompanied with terms cleaning as well, it may move the whole thing on to new quality.
But. I am not the one responsible, I do not see all the differing implications.
I'm in the same boat. I see the attraction, very long run. Perhaps others will weigh in.
On Tue, Oct 23, 2012 at 11:53 AM, Brendan Eich <brendan at mozilla.org> wrote:
Herby Vojčík wrote:
Brendan Eich wrote:
Herby Vojčík wrote:
By the way, let deprecate (that is, recommend not to use) proto and introduce @parent (or other term) instead, while both having the same behaviour.
We could do this, given symbols, but would it help? New code could use it in the next several years only with an ES6->ES5 compiler and ignoring IE on desktop; this is a real possibility for "mobile developers", self-defined. But developers could just as well use proto and probably will skip the compiler without strong need for other ES6 features.
This means we're adding a nicer synonym for the very long run. Which means two things, more total surface syntax, more "cruft" from certain points of view. Is it worth it?
I think 'cruft' is too strong. There will be two things that do the same thing, one 'legacy', one new. Though I can not give an example, I have the impression things like that happens (use X, there is Y for compatibility, for it is not endorsed now...) often.
Number.isNaN adds value, by not coercing non-number arguments to number, compared to isNaN. Ditto similar innovations, see brendaneich.com/2012/**10/harmony-of-dreams-come-**truebrendaneich.com/2012/10/harmony-of-dreams-come-truenear the bottom.
By contrast, @parent would be no better in function (ignore form) from proto.
Isn't there some value in stratification? Wouldn't this make it possible to move proto back to a non-normative note, so that one day, maybe...just maybe, it can be forgotten altogether? I an Object.setPrototypeOf API has been suggested before -- but if it were specified with @prototype then all legacy uses of proto could be shimmed inside this official API surface. You say "nicer synomym for the very long run", but in the verylong run why couldn't it be a true replacement?
Considering all the opinions around accessor usage in the standard, I'd think eliminating this dunder-wart would be a pretty nice aesthetic win. I know proto isn't going anywhere for a long time, but does it really have to be standardized, especially when there's more "pure" alternative?
On Tue, Oct 23, 2012 at 8:53 AM, Brendan Eich <brendan at mozilla.org> wrote:
I'm in the same boat. I see the attraction, very long run. Perhaps others will weigh in.
I guess very few developers off this list know that [[Prototype]] exists. That is, the special double square bracket syntax is not something developers use. Thus no change in [[Prototype]] will make an improvement outside this list.
On the other hand, Axel's point is taken: the subject of 'prototype' is confusing. But this is only partly terminology; much of the problem is built in to the system. The operation of 'new' is weird, the flexibility allowed by proto is unsettling and Object.create() completes the puzzle.
I think Axel's original post had a good suggestion: in descriptions modify the property with its container. Consider: An object's |proto| property references its constructor's |prototype| property. Notice I paired object with proto and constructor with prototype. Now I mangle Axel:
- prototype (of an obj): the “fallback” object, access via proto
- prototype (of a constructor): value of Constr.prototype If we consistently changed documentation (MDN etc) to use "prototype of and object" and "prototype of a constructor" perhaps the ambiguity would be less.
(I suggest avoiding "prototype of a type" to avoid a similar issue with the terminology for 'type').
jjb
Dean Landolt wrote:
On Tue, Oct 23, 2012 at 11:53 AM, Brendan Eich <brendan at mozilla.org <mailto:brendan at mozilla.org>> wrote:
Herby Vojčík wrote: Brendan Eich wrote: Herby Vojčík wrote: By the way, let deprecate (that is, recommend not to use) __proto__ and introduce @parent (or other term) instead, while both having the same behaviour. We could do this, given symbols, but would it help? New code could use it in the next several years only with an ES6->ES5 compiler and ignoring IE on desktop; this is a real possibility for "mobile developers", self-defined. But developers could just as well use __proto__ and probably will skip the compiler without strong need for other ES6 features. This means we're adding a nicer synonym for the very long run. Which means two things, more total surface syntax, more "cruft" from certain points of view. Is it worth it? I think 'cruft' is too strong. There will be two things that do the same thing, one 'legacy', one new. Though I can not give an example, I have the impression things like that happens (use X, there is Y for compatibility, for it is not endorsed now...) often. Number.isNaN adds value, by not coercing non-number arguments to number, compared to isNaN. Ditto similar innovations, see https://brendaneich.com/2012/10/harmony-of-dreams-come-true/ near the bottom. By contrast, @parent would be no better in function (ignore form) from __proto__.
Isn't there some value in stratification?
You mean using a symbol not a string? "Stratification" usual means a meta-layer API not defined in a base-level object, not a name-kind change.
Wouldn't this make it possible to move proto back to a non-normative note, so that one day,
We don't have plans to remove things. It's hard to make such on the web. We could hope, but it's not really relevant.
maybe...just maybe, it can be forgotten altogether? I an Object.setPrototypeOf API has been suggested before -- but if it were specified with @prototype then all legacy uses of proto could be shimmed inside this official API surface.
-
No, we rejected a static method because it would have to be neutered in SES environments but those may want to mash up within one realm, so Object.foo is a pigeon-hole problem and neutering breaks valid users in the non-SES code.
-
What's more, having two things forever instead of three hardly beats having one thing, unless you over-weight the cost of dunder-proto. A rose by any other name...
You say "nicer synomym for the very long run", but in the very long run why couldn't it be a true replacement?
Because we cannot and do not plan on removing anything. It's not practical on the web. It might be possible, who knows? But in realistic, predictable, and foreseeable terms, all we are doing is adding complexity and redundancy (ignoring the undesirable point (1) above).
The web isn't pretty. It's not the Mona Lisa. But (as Anders patiently points out in the GOTO interview mentioned recently) all practical, mature languages have quirks and ugly spots.
Not to defend JS too much, it could be prettier -- but this thread won't actually achieve anything as far as the eye can see. Do rouge and lipstick make the wart of proto into a beauty spot? Only if you turn a blind eye.
Considering all the opinions around accessor usage in the standard, I'd think eliminating this dunder-wart would be a pretty nice aesthetic win.
Not sure what you mean. I'm ok with either magic data or accessor with poisoned reflection, and either is sufficiently compatible. Doesn't affect anything in this thread.
When I explained proto at JSConf, the first question was: “How is proto better than the ‘prototype’ property that all constructors already have?”
|On the other hand, Axel's point is taken: the subject of 'prototype' |is confusing. But this is only partly terminology; much of the problem |is built in to the system. The operation of 'new' is weird, the |flexibility allowed by proto is unsettling and Object.create() |completes the puzzle.
Even to those familiar with the concept of prototypical programming, the JS version is confusing: in Self, "proto" would have been a "parent slot", the content of ".prototype" would have been a "parent object", while Self's idea of a "prototype" would have been an ur-object from which a new instance was copied; both copying and ur-object are implicit in JS constructors.
With proto standardized, there is less need to refer to things outside the language, such as [[Prototype]]. That also alleviates the issue of overloading and re-interpreting the word "prototype".
We could look for a set of equations (involving code fragments instead of spec language) to express 'prototypical inheritance on a t-shirt/on one slide'. Something like (cheating a little, where suitable syntax seems to be missing:-(
0 Constructor.proto === Function Constructor.prototype.constructor === Constructor
1 ( new C(...args) ).proto === C.prototype
2 new C(...args) === C.apply( { proto : C.prototype } , ...args )
3 Object.create( p , {...properties} ) === { proto : p, ...properties}
Expressing recursive selection is trickier (eg, it would be good to be able to split an object into proto and proto-free own properties, to create objects from properties, and to have let-expressions)
4 { proto : p, ...properties}[m] === { proto : p, ...properties }.hasOwnProperty(m) ? ( ({ m: v }) => v )( { ...properties } ) // select directly : ( p===null ? undefined : p[m] ) // try up the chain
If we can flesh out this idea, it could become a cheat sheet that is easier to digest than the formal language of the spec and could support attempts to explain the ideas in informal language.
Languages like Lisp, Smalltalk and Prolog could express their core on a "page", via meta-circular interpreters. How many pages for JS?-)
Claus
I like the “t-shirt” approach.
0 Constructor.proto === Function
Beware (I frequently get this wrong, too): Constructor.proto === Function.prototype
Constructor.prototype.constructor === Constructor
1 ( new C(...args) ).proto === C.prototype
2 new C(...args) === C.apply( { proto : C.prototype } , ...args )
3 Object.create( p , {...properties} ) === { proto : p, ...properties}
properties
are property descriptors, so this assertion doesn’t hold.
Expressing recursive selection is trickier (eg, it would be good to be able to split an object into proto and proto-free own properties, to create objects from properties, and to have let-expressions)
Suggestion: create a chain, use it to demonstrate these concepts. But we are approaching XXL t-shirts then.
Not to defend JS too much, it could be prettier -- but this thread won't actually achieve anything as far as the eye can see. Do rouge and lipstick make the wart of proto into a beauty spot? Only if you turn a blind eye.
I agree. I was looking for feedback on terminology and on how to explain things and got some great suggestions.
Given that proto is the only ES6 dunder property, I’m fine with it. Where it is problematic (mixing object level and meta level), @proto (or similar) wouldn’t be an improvement.
Axel
This probably comes across as being overly obsessed with details, but I think that clear terminology matters. It would be nice if we could avoid the term “prototype” being overloaded in ECMAScript. It still trips up JS beginners: When I explained proto at JSConf, the first question was: “How is proto better than the ‘prototype’ property that all constructors already have?”
How about the following?
Not entirely happy with this, but it’s better than using the same word twice. And it corresponds to how one would pronounce the property names (modulo “dunder”). If the above is OK then we could rename [[Prototype]] to [[Proto]].
Axel