Prototypes as the new class declaration

Irakli Gozalishvili rfobic at gmail.com
Fri Jun 17 05:14:17 PDT 2011


I really like this direction, I think it much better feet for JS than a class sugar!

I also experimented something similar not a long time ago as a library: https://github.com/Gozala/selfish/blob/master/selfish.js
Also as an extension to the Built-ins: https://gist.github.com/d33befccbe1e0ed492d5


Regards
--
Irakli Gozalishvili
Web: http://www.jeditoolkit.com/
Address: 29 Rue Saint-Georges, 75009 Paris, France (http://goo.gl/maps/3CHu)


On Thursday, 2011-06-16 at 05:20 , Allen Wirfs-Brock wrote:

> 
> On Jun 15, 2011, at 12:25 AM, Brendan Eich wrote:
> > On Jun 14, 2011, at 11:59 PM, Axel Rauschmayer wrote:
> > > Wouldn’t you add a class method like this?
> > > 
> > > const SkinnedMesh = THREE.Mesh <| {
> > > cm: function() {
> > > }
> > > ...
> > > };
> > > Then it could be invoked as SkinnedMesh.cm() (which to me is what a class method is: there is a class named SkinnedMesh and it has a method cm()).
> > > 
> > > Furthermore, it would automatically be inherited:
> > > 
> > > const SkinnedMeshExtended = SkinnedMesh <| { ... }
> > > 
> > > Then the following class method could also be called:
> > > 
> > > SkinnedMeshExtended.cm()
> > > 
> > > Right?
> > It has the right plurality -- I mean, the prototype is a singleton and so is the constructor.
> > 
> > You invoke it on the name of the abstraction, via dot -- check. Just like String.fromCharCode.
> > 
> > So let's go with that built-in: new String("hi") instanceof String is true, and same works for SkinnedMesh in both the classes proposal and Allen's class-free variant.
> > 
> > But String.fromCharCode is not inherited such that "hi".fromCharCode delegates to String.fromCharCode. Hrm.
> > 
> > I don't mean to single out String as a built-in. Whether user-defined or built-in, today's constructor functions can have "class properties" that are not inherited by instances. That seems like it could matter, e.g. to avoid having Object.keys suddenly make keys properties appear in all objects -- including in the global object!
> > 
> 
> As far as I can tell, the equivalent of "class methods" just don't show up in the self libraries.
> 
> There are various alternatives that are used:
> 
> For something like the Object methods self would simply use a singleton object with those methods. That's essentially what we did when we decided to attach them to Object for ES5. Object was just a convenient singleton that already existed. EG,
>  ObjectReflection.create()
> 
> For something like String.fromCharCode there are several alternative strategies that might be used.
> 
> For something as trivial as this, it just might be added as a method to String (the prototype) and it could be directly invoked there or via any available instance (if you weren't concerned about possible instance specific over-rides). EG,
>  String.newCharCode(0) or "".newCharCode(0)
> 
> Or, since the most common form of fromCharCode essentially converts a number to a char, it might be added Number.prototype EG,
>  0.asCharacter()
> or for the multiple value case Array.prototype, EG,
>  [1,2,3,4].asStringFromCharCodes()
> 
> Alternatively, if there was a more complex set of methods or there was an a strong reason why you didn't want instances to share the behavior. You would create a separate singleton helper/factory object to hold the methods, EG,
>  StringBulider.fromCharCode(1,2,3,4,5)
>  StringBuilder.fromStrings("abc","def","xyz")
> 
> Of course, such an object could participate in its own inheritance hierarchy that was decoupled from Strings, EG,
>  let I18NStringBuilder = StringBuilder <| {fromLocaleString(template,locate) {...}};
> 
> And if you didn't want to "globally" name such factories you can make the factory be a property of the instances. EG,
> String.builder.fromCharCode(1,2,3);
> 
> This is almost the same as hanging methods off the constructor function. However, practically speaking in ES, it is more awkward to attach properties to the constructor. You would probably say:
>  {
> ...
>  constructor: (Function.prototype <| {fromCharCode(...args) {}...}) <| function (arg) { /* constructor body */
>  }
> }
> which seems more awkward than:
>  {
> ...
>  ~builder: {fromCharCode(...args) {}...},
>  constructor (arg) { /* constructor body */
>  }
> }
> 
> 
> These examples seem to suggest that there are plenty of reasonable ways to approach what currently would be constructor methods. However, they all require some rethinking that starts with the concept that you name the prototype and not the constructor. The biggest hurdle to me seems to be that the existing built in objects don't follow that pattern. One way around that might be to give the built-in prototypes their own explicit names (in a module). For example: ProtoString, ProtoArray, etc. and then use those names in as the new way to talk about those abstractions. (More radical and probably less acceptable would be to actually re-associate the names String, Array, etc. with the prototypes using such a module).
> 
> A basic question is whether learning to think about prototypes as the key named abstraction is more or less of a burden than learning when and how to use a class declaration.
> 
> Allen
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org (mailto:es-discuss at mozilla.org)
> https://mail.mozilla.org/listinfo/es-discuss

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110617/501af90e/attachment-0001.html>


More information about the es-discuss mailing list