Why “class” Doesn’t Mean What You Think It Means

There’s a lot of “don’t turn it into Java!” in the comments on my last post, and I feel it needs a response — and not because I think there’s anything to like about Java’s class or type systems (perhaps that they exist at all? I’m torn on even that).

Lets look at some possible ES.next code and walk through how it relates to today’s equivalent JS:

module widgets {
  // ...
 
  export class DropDownButton extends Widget {
    constructor(attributes) {
      super(attributes);
      this.buildUI();
    }
 
    buildUI() {
      this.domNode.onclick = (e) -> {
        // ...
      };
    }
  }
}

Ignoring the semantic improvements of Harmony modules over the module patterns we’re using today, we can see a pretty straight-up de-sugaring of that to today’s JS with an emphasis on the many and varied uses of the word function:

var widgets = (function(global) {
  // ...
 
  function DropDownButton(attributes) {
    Widget.call(this, attributes);
    this.buildUI();
  }
 
  DropDownButton.prototype = Object.create(Widget.prototype, {
    constructor: { value: DropDownButton },
    buildUI:     {
      value: function(e) {
        this.domNode.onclick = function(e) {
          // ...
        }
      }
    }
  });
})(this);

What you should take away from this isn’t that we’re turning JS into Java, it’s that we’re making it easier to read, AND THAT’S ALL. Once more for effect: what class means in ES6 is function. Or at least one of the things you currently do with function.

Better yet, we’re blessing a single pattern which you can use with old-style classes just as easily as you do today. I’ll leave it as an exercise for you to name all the different class patterns and systems that do nearly the same thing in slightly incompatible ways today. It’s a very long list.

If you like JS, and you like functions + prototypes (I do!), you have nothing to fear from the sugar we’re adding in ES6.

Update: A lunchtime conversation here at DojoConf today reminded me of perhaps the largest thing that this new system doesn’t do; ES.next aren’t tied to a Java-like type system. Many of the conjoined fears of Java come from the very real pain created by a strict, nominal type system, and nobody in the committee is proposing a mistake like that — least of all me.

6 Comments

  1. Posted September 16, 2011 at 7:56 pm | Permalink

    thanks for the clarification from your last post. the only concern I have with using the word “class” is that it comes with so much baggage. maybe just use the word “prototype” instead of “class”.

    one thing I’ve never understood is why do all proto-classical implementations only allow to extend from one object? as long as there are no conflicting names it’s perfectly reasonable to generate a new object from any number of other objects. how would that syntax be implemented? something like:

    export class HugeButton extends BigButton,BiggerButton {}

  2. Posted September 16, 2011 at 9:49 pm | Permalink

    Hi Trevor,

    “prototype” means something today, and the we’re also defining the constructor and *instance* object structure here, so perhaps “prototype” would fit, but then we loose the isomorphicness with “function”. I’m not sure it matters, though…just as long as we get an easy-to-type-and-read solution that means something sensible in ES5 de-sugaring.

    As for multiple inheritance: not gonna happen. There are multi-proto languages in the world, but ES isn’t one of them and it would present probably the single largest change to the object model since the first version of the language to do it.

    What I’m hopeful that we *can* do is to start taking the pressure off of inheritance with something like Traits which can have multiple composition per class. Here’s some example syntax of the early versions of this supported today by Traceur:

    http://code.google.com/p/traceur-compiler/wiki/LanguageFeatures#Traits

    Regards

  3. Jonathan Dum
    Posted September 17, 2011 at 1:50 pm | Permalink

    I’m against shortening of syntax to symbols and shorter keywords. I much rather ES.next use full words and here’s why:

    Novices and learners don’t care about how long it takes to write one line of code, they focus on understanding what they are doing and making it work.

    Experienced users want to write as much as possible in as little time as possible. This is where text-expanders and IDEs come in. Shortening typing speed at the expense of readability should not fall under the syntax’s obligation, rather the user.

    Sure some people would complain about having to type `public function myFunc(value() { }` over and over again, but the smart programmers will encapsulate that to a text-expander as `pfunc`+tab or whatever works for *them*.

  4. Posted September 18, 2011 at 12:39 pm | Permalink

    Hi Jonathan,

    Novices and learners take patterns and re-use them. Arguing for long names — which might help discoverability for infrequently used — misses the point. Common idioms gain meaning in part through name and in part through use. The more common a system/idiom, the more the balance shifts to “use” and away from “name”. In the context of the language and syntax, that’s most often the case. It’s a mis-use of syntax to design for discoverability — even when that might absolutely be the right thing to do for a library.

  5. Rahul Devaskar (@apostopher)
    Posted September 18, 2011 at 9:05 pm | Permalink

    Nice post.. ES6 will surely make JS code look cleaner.
    In the above sample how does ‘export’ relate to ES5? does it mean DropDownButton is now global.DropDownButton?

  6. Posted September 29, 2011 at 9:19 am | Permalink

    @Jonathan,

    Keep beating that drum! Fast typing and slow reading is bass ackwards, for sure.

    @Alec,

    Uh, don’t want to put words in Jonathan’s mouth but he did say “full words”, not “long names”. People apologize for, for example, the module pattern by claiming it’s a “common idiom”. That’s another way of saying beginners can’t read it – not a hallmark of great code.