Prototypes as the new class declaration

Brendan Eich brendan at mozilla.com
Sat Jun 18 08:09:35 PDT 2011


On Jun 18, 2011, at 7:29 AM, Axel Rauschmayer wrote:

> Where would the prototype of the new instance come from? Would SkinnedMesh.constructor.prototype point to SkinnedMesh?

Of course -- Allen's proposal just "rotates" the (constructor, prototype) pair so the named or "outer" object is the prototype.

This matches the syntax. It's a bit odd that class syntax has a body that contains constructor, yet the class name binds to that inner constructor function. It works, or we can make it work -- it just seems unusual given the otherwise-pellucid rules for naming objects expressed by braced bodies (initialisers, functions).


> Prototypes already have a property called “constructor”, so this part of it works out nicely.

Exactly.

Now, we could have a "second protocol" as Irakli's gists show. He wires up both per-instance and "static" (ugh, I mean constructor-side) 'new' methods that bottom out by calling the constructor. This is not quite the second protocol you proposed that we agreed would be less desirable, all else equal, than a single constructor protocol. It's a layering on top, rather than an additional parallel novel protocol.

For reference, Irakli's https://gist.github.com/d33befccbe1e0ed492d5 has:

example.js #raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const SkinnedMesh = THREE.Mesh.extend({
  new: function SkinnedMesh(geometry, materials) {
    var self = THREE.Mesh.new.apply(SkinnedMesh, arguments);
    // initialize instance properties
    self.identityMatrix = THREE.Matrix4.new();
    self.bones = [];
    self.boneMatrices = [];
    return self;
  },
  update: function(camera) {
    ...
    // call base version of same method
    THREE.Mesh.update.call(this);
  }
});
selfish.js #raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/* vim:set ts=2 sw=2 sts=2 expandtab */
/*jshint undef: true es5: true node: true devel: true evil: true
         forin: true latedef: false supernew: true */
/*global define: true */


"use strict";

Object.prototype.new = function new() {
  return new this.constructor();
};
Object.prototype.extend = function extend(properties) {
  var constructor = new Function(), descriptor = {};
  properties = properties || {};
  Object.getOwnPropertyNames(properties).forEach(function(name) {
    descriptor[name] = Object.getOwnPropertyDescriptor(properties, name);
  });
  descriptor.constructor = { value: constructor };
  return Object.freeze(constructor.prototype = Object.create(this, descriptor));
};

Object.new = function new() {
  return Object.prototype.new();
};
Object.extend = function extend(properties) {
  return Object.prototype.extend(properties);
};
Comments are parsed with GitHub Flavored Markdown


The Object.prototype.extend method serves the role of <| but also wires up 'constructor' automatically. The user has only to define a 'new' method. This was the more complicated option against which I argued when we mooted classes last month, on the grounds that we did not want to pre-empt 'new', and we didn't need two names ('constructor' and 'new') where one would do -- and where one has done for JS for 16 years.

But beyond the 'new' convenience/prettiness, Irakli's gist builds on Allen's idea of naming the prototype instead of the constructor. extend returns the prototype (not sure why it freezes; let's not worry about that right now ;-). With prototype-first abstraction naming, the argument that we don't need classes becomes stronger. The 'new' protocol allows old-style builtins and user-defined functions to be constructed by calling .new on their instances (delegating up to Object.prototype.new).

For me, this does not close the deal that we don't need classes. But it is getting close, and it is working in the right direction. I don't want to kill classes, but I think we all (Harmony types at least) want to minimize additions to the language and prefer orthogonal primitives that have good usability, and which compose cleanly.
/be
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110618/3278781a/attachment-0001.html>


More information about the es-discuss mailing list