On 06.08.2014 06:38, Rick Waldron wrote:


On Tuesday, August 5, 2014, Domenic Denicola <dome...@domenicdenicola.com <mailto:dome...@domenicdenicola.com>> wrote:

    I sympathize; I have always found the fact that bare `super()`
    works to be confusing.


When a bare super() call appears in a method (whether constructor or not) it can only have _one_ _meaning_ and that's a call to a method of the same name in the parent class. This isn't particularly innovative: John Resig's Simple JavaScript Inheritance[0]—arguably one of the most widely used (many clones, forks and spin-offs exist) "abstract class" techniques—provides `this._super()` which does the same thing that ES6 super() does. This pattern existed before and has been repeated throughout many libraries that have stood out over the years: Prototype, Dojo, Ext.js and certainly others. CoffeeScript implements super() this way as well.


Rick


[0] http://ejohn.org/blog/simple-javascript-inheritance/


_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

I wonder why you chose that way in the spec. An issue I can see here is that mixin-based inheritance on a per-method basis won't work properly as expected.

In my game engine lycheeJS, I'm using a mixin based inheritance to allow

a) inclusions based on feature detection (html, nodejs, v8gl, etc.)
b) inclusions in a specified order (a la a extends b extends c)
c) overwrites of your method with super calls to both via direct b.prototype (or c.prototype) access d) mixin based includes that allow inclusions _of single methods_ of other classes


Simplified Example:

var a = function(settings) {
  // moar stuff
  b.call(this,settings);
  c.call(this,settings);
};

a.prototype = { render: function() {
  c.prototype.render.call(this);
  doCustomStuffInBetween();
  b.prototype.render.call(this);
}};

The last reasons (c, d) are very important to my game engine, because it allows inclusion of single "public" methods. For example, you can reuse a 2D render() method of a ui.State for rendering the UI layer, then draw something in 3D on top of it via the game.State.

To access those namespaces properly, I have to create all definitions inside a closure with "dynamic" arguments. For example:

lychee.define('lychee.Renderer').exports(function(lychee, global, attachments) {}); lychee.define('game.Renderer').exports(function(lychee, game, global, attachments) {});

That allows me some essential things for the engine concept:
a) every definition can be exported in a sandbox
b) theoretically sandboxes of supports() (feature detection callbacks) are possible with new Proxies, currently they have to be executed global (different story of detecting type-based access to properties that are not existing at runtime and need to be dispatched) c) every definition can be serialized as a string and deserialized later, in sandboxed state without requiring access to global properties d) global accesses to properties or bound variables from outer scopes are easily traceable via try/catch e) global can be faked, it is not existing and not "window", it's a reference to lychee.Environment's global property.


An example of this mixin-based inheritance usage can be found here:

https://github.com/LazerUnicorns/lycheeJS/blob/development-0.8/projects/boilerplate/source/entity/Circle.js#L99

PS: If you are curious, install lycheeJS via README.md and run the localhost:8080/projects/boilerplate. Then call lychee.environment.serialize(); which creates the JSON that is deserializable (and injectable) at runtime.


Also, what is *REALLY* important (I can't stress that enough). JavaScript has a huge bonus when being compared to other programming languages. Namespaces are just objects in global scope that can exist at runtime, not necessarily at compile time or definition time. Access to lychee.game.Main is just new lychee.Environment().global.lychee.game.Main. The advantage here is that global can be faked as a sandbox and can be isolated to trace errors occuring on a per-definition base at runtime. (Namely remote debugging and remote code injection via websockets)

This leads to the possibility of inclusion of different libraries under a _different namespace_. All libraries think they have say the "game" namespace, but in fact, you can include them in a different project under a custom namespace. Every library, if sandboxed, will never pollute the "global namespace".

These features were the killer decision for me to use JavaScript as a game engine base, otherwise I probably would've used Lua (I'm honest).

I would recommend having those listed features in mind when talking about super() and namespaces, because the current spec still will prevent me from using native "class" keyword in JavaScript.

If newbies ask me if they should use classes, I say no to them, because I still think the featureset of a mixin-based inheritance (leading to fancy prototype copying and sealing) is still better.


Cheers,
~Christoph

_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to