Hi,

I'll do a 2 parts answer. First, I'll answer the blog post, second, I'll
try to take a step back and discuss composition in JavaScript.

=== Part I ===

Le 16/03/2012 17:04, Kevin Smith a écrit :
> Rather than abuse your inbox, I published this as a blog entry:
>
> http://blog.khs4473.com/2012/03/using-object-literals-as-classes.html
>
> Summary:  It has been suggested that extended object literals can be
> used to define class-like abstractions, and that consequently class
> syntax is not necessary.
I'm not sure the conclusion has ever been that strict. Having the proto
and extend operator version is not mutually exclusive with a class
syntax. I don't remember having read that at least.

> I analyze the implications from the point of view of a library developer.
>
> Comments?
The "Class"-like libraries started to compensate missing things in the
language specifically when it came to loosely-coupled composition of
abstractions.
New language features (the proto operator, the extend operator, maybe
even traits if they make it to the language) are here to fill a gap in
the language expressiveness.

I'm a bit surprised by the approach of the blog post which consists in
studying how new features will fit in or help ameliorate a Class library.



"`useMethod` calls a private method here. But does this work? Privately
named properties aren't enumerable and don't show up in
Object.getOwnPropertyNames. *My class library works* by reading the keys
from the input object and attaching them to a new object with the
correct prototype chain. But..." (emphasis added)
=> your library works in a certain way and you won't be able to use your
exact implementation in concordance with how private names have been
defined.
Maybe the private name feature could be reconsidered or maybe your
implementation could be reconsidered.

-----
_new : function(textview){
    TextRange.call(this);
    EventTarget.call(this);
    EventSubscriber.call(this);
   
    this.blabla = ...
}
-----
When I read this code, questions that comes to mind :
What if conflicting names are defined in the TextRange, EventTarget or
EventSubscriber?
Does the order matter? Certainly so and it would make your composition
mechanism not that declarative.
Anyway, the answers do not really matter. What does is that it's not
obvious from reading the code what happens. It's fine-ish for a library
of your choice, but it's annoying when discussing language features.


"`super.constructor` is annoyingly verbose, and I might as well just use
BaseClass.call(this). No gains there."
=> super will be a keyword. As such, it can be highlighted by IDEs. It
can help readability.
It also avoids the repetition:
-----
{
extends: TextRange,
_new: function(textView) {
        TextRange.call(this);
    }
}
-----
With super, you know you're calling the thing you extend from. Change it
in one place, it applies everywhere unlike in your case where you have
to remember to change something in 2 places.


" For library authors, object literal extensions do not provide a
replacement for class construction libraries."
=> This conclusion is rather surprising. You haven't assessed object
literal extensions to solve a problem, but just tried to see how they
impact your Class construction library.


"The individual extensions provide some support in the form of shorter
method syntax and static delegation, but fall short of providing the
tools to create a fully featured class library. "
=> It wasn't a goal. If creating a fully-featured class library had been
a goal, I think there would be a strawman for that.


"Furthermore, it's not clear at the present time that prototype
delegation is useful outside of the context of class-like abstractions,
and the necessity of rebinding "super" for every method indicates that
the "super" semantics are being defined at the wrong level of abstraction."
=> ... or that you're trying to use a feature in a way it was not design
for. In which case, don't use the feature.



=== Part II ===

So, let's take a step back.
Before Class libraries, JavaScript did not have an easy way to express
something like:
"I want a Ninja to be a Person with a sword".

I can think of these ways (not an exhaustive list):
-----
// 1) with methods as own properties of persons
function Ninja(){
    Person.call(this, "Joe"); // getting all persons properties
    // This style forces a bit objects to only be normal objects
    // They can't be arrays, functions, DOM objects or proxies for instance
    this.sword = "Excalibur";
}

// 2) with methods as own properties of persons
function Ninja(){
  var init = {}; // could be anything, like arrays or functions.
  var p = new Person("Emily");
  // pour all p properties in 'init' with a for-in loop or whatever method
  // alternatively copy values and forward methods
  this.sword = "Excalibur";
}

// 3) with person methods in Person.prototype
function Ninja(){
    Person.call(this); // just properties
    this.sword = "Excalibur";

}
Ninja.prototype = Object.create(Person.prototype)
Ninja.prototype.method = function(){};
/* Encapsulation is lost in that case since the inherited methods need
to know the state of the object which has to be public */
-----
All of this is awkward to say the least. Comments and discussion welcome
on this list.


Came along Class libraries which provided something a bit more
declarative, but had one of the limitations of the above method anyway.

Fast forward to 2012. How do I define a Ninja with the new operators?
----
var Ninja = Person <| function(){
    super.constructor();
    this.sword = "Excalibur";
}
----
Encapsulation will not be compromised. Additionally private names will
work fine here.
If the base class is Array or WeakMap, it works as well.


In the end, JavaScript is still not a good language for classes library,
but I think the new operators help solving most (maybe not all) problems
Class libraries were initially introduced for.

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

Reply via email to