Hacker News new | past | comments | ask | show | jobs | submit login
A Few New Things Coming To JavaScript (addyosmani.com)
153 points by twapi on Nov 22, 2012 | hide | past | web | favorite | 58 comments

Some of the more utilitarian features are kind of nice, but I'm not sure how I feel about the module and class support.

I understand that the current situation is a bit annoying, but one of the attractive things to me about ES is that you can fake near anything using the prototypical nature of the language--adding this other stuff seems to me to be bloating things for the sake of a little less effort when trying to use ES like Java or something similar.

ES is an ugly little language, but at least it's little.

EDIT: I'd rather they simply standardize a lot of, say, the underscore.js functionality into the core APIs.

The "classes" are merely a short-hand for creating constructor functions with their prototype property already assigned: they add no new semantic complexity to the language, they are mere syntax.

They also add class-side inheritance.

This allows the constructor to inherit its properties from a parent constructor:

    class Class {}
    Class.hello = "hello";

    class SubClass extends Class {}
    SubClass.hello // "hello"
This doesn't add any new semantics on top of the already-approved `__proto__` (which already exists in all browsers but IE):

    Class = function() {};
    Class.hello = "hello";

    SubClass = function() {};
    SubClass.__proto__ = Class;
    SubClass.hello // "hello"
EDIT: Oh, and they add `super`:

    class Speaker {
      say(string) { console.log(string); }

    class Yeller extends Speaker {
      say(string) { super(string.toUpperCase()); }

    new Yeller().say("hi") // "HI"

About the last example, I think you meant :

See: http://wiki.ecmascript.org/doku.php?id=strawman:maximally_mi...

Ah, I'd forgotten it now mutated [[Prototype]] and not the prototype property's [[Prototype]] (IIRC, earlier drafts had it mutating the latter, i.e., `SubClass.prototype.__proto__`).

`super` is indeed new semantics though, so that is definitely true.

Yeah, they're syntactic sugar.

I'd bet you they will allow browsers to optimize their compilation steps, so they are more then just sugar.

No, they're just sugar. It has no relation to whether you can use them to optimise things or not.

It's called Type Specialization http://dl.acm.org/citation.cfm?id=1542528

Class declarations will be equivalent (can be desugared to) a function declaration and some manipulations of the function's prototype. JS VMs already optimize this pattern, so why should syntax sugar for classes be anything special for the compiler?

Because it takes time and CPU cycles for them to figure out what is a Type and what is not. They don't know how much memory to allocate to these objects for instance, but now with classes they will know types immediately.

While I think I understand you, and maybe a little sympathetic to keeping the language little, I simply cannot agree because what you said is basically contradictory.

It's same old argument I guess, but MIPS is simple and consists of only very few instructions. Are you going to program in MIPS everyday? The same argument goes for JS. JS is too little in terms of functionality, so it requires lots of ceremony to write common idioms that other languages have had for decades. Javascript is a terrible language as it stands now, but its adoption and usage has matured enough that there's a lot less risk in pissing people off by adding syntactic sugar on idioms that people already use. I actually welcome these ES6 additions wholeheartedly.

So, the proper argument here would be in support of something like CoffeeScript which compiles to JS, much as we would expect C compilers to generate our MIPS code for us.

My concern is basically born out of my background using C++; a lot of very well-meaning additions have been made over time to that language, and now it's so sprawly that using it at different shops is annoying. C++ these days is basically begging to be replaced by C with bindings to a scripting engine, because it's too damned unwieldy for most other purposes (the joke goes, everybody uses a different 90% of the features).

I'm just concerned that JavaScript, an elegant if flawed little language, is going to get enterprisified by well-meaning developers who lack foresight and who haven't learned from others.

That's a terrible analogy. JS is small and simple but it's far far far more powerful and friendly than MIPS. What functionality is missing from JavaScript that needs to be supplemented by the things outlined in this post? What kind of things are you doing that "require a lot of ceremony?"


Would you like to type this?

    var myModule = (function(root){
        var lib = {};
        root.lib = lib;
        return lib;
Or this?

    module myModule = {
        export //blah blah blah
Data structures.

There's not map or set in JS even to this day that actually acts like a map or set you've learned in your data structure class. Object literal is a poor substitution for a map.

Import, classes, and default parameters have a very strong resemblance to CoffeeScript. In fact, Osmani expresses succinctly -- better than I could have -- why I love Coffee so much over JS syntax:

    Classes in ES.next are there to provide a declarative
    surface for the semantics we're used to (e.g functions,
    prototypes) so that developer intent is expressed
    instead of the underlying imperative mechanics.
The Observables are so much like MVVM in KnockoutJS or SpineJS. (Plus, Spine is written in Coffee, and includes makeArray and a module pattern). I know many developers can't see the advantage to Coffee, but if you are interested in ES6 features you can use them right now by compiling Coffee to JS/ES5. Osmani didn't mention array comprehensions (ES6/JS1.7) or generators (ES6/JS1.8) but they are in Coffee as well.

So please, if you are interested in the future of JS, take another look at Coffee. And bring on ES6!

While comprehension is, generators are not part of Coffee-script.

I should have been more specific. The generator expressions specified in Harmony [1] are the exact same syntax as in CoffeeScript.

[1] http://wiki.ecmascript.org/doku.php?id=harmony:generator_exp...

That would be because both are lifted from Python.

And it is not the exact same syntax (Harmony uses `for (e0 of e1)` paralleling its for-of iteration syntax and semantics), and more importantly the semantics are completely different. Finally, the syntactic similarity would already be covered by the array comprehension mention.

Thus, there's nothing even remotely close to generator expressions in coffeescript at this point, as far as I know.

Well, I suppose downvotes are what I get for commenting at 6 in the morning at 35,000 ft. Correct, as the article mentions Harmony takes many cues from Python, as does Coffee, and Coffee cannot magically create features that aren't supported by the underlying JS.

However, it is possible to get a near-equivalent of generators (albeit with more overhead) using Continuation Passing Style and Iced CoffeeScript await/defer or another CPS lib. There are many who have explored this concept before myself, and I am now inspired to create an example to demonstrate IcedCS's ability with such a concept once I'm through the holiday.

Actually, using ICS and CPS to build generators forces a reversed approach. With generators is the called function to own the process, in await/defer is the calling context which knows about the "generator like" functionality.

And you're completely right about Coffee not able to implement ES6 generators.

They're adding a bunch of new features and yet they ignore one of JavaScript's most glaring shortcomings: not tail call elimination. Honestly, I would be ecstatic if this was the only change to the language.

That said, I'm excited about some things. In particular, I really like proxies--being able to customize the behavior of your language (in this case, how objects work) transparently is a good way to decouple parts of your code. Now you can change how an object's properties behave without having to rewrite client code to use methods. Having modules built into the language would be nice too: having everybody use the same system for importing code will make life easier for everyone.

The article mentions that sets "are an effective means of creating ordered list of values". Is this just a mistake on the author's part, or are sets actually to be ordered? Any sane set data type should not be ordered for two reasons: the obvious hash-based implementation isn't, and the actual abstraction (a mathematical set) isn't either.

I believe that they are also planning to add more support for iterators over arrays, maps and sets, which wasn't covered in the blog post. I personally think this is a big mistake. In the recent past, I've had to use iterators pretty widely for a little project. (I was also using a coroutine system very similar to Python's generators.) I found iterators to be a horrible headache. They are essentially anti-functional: they introduce additional state even for benign things like iterating through a sequence! You can't pass them around, you can't use them twice, you have to be careful when writing functions over them... it's really not pleasant.

Anyhow, some of the changes are certainly interesting--both in good ways and in bad ways. There's also always the question of how long it will take for enough browsers to support it. However, with the recent push towards automatically and quickly updating browsers, this shouldn't be as bad as in the past.

Good stuff there, but unfortunately we'll have to wait a few more years for these to be usable (at least for me).

Modules, block scoping, default parameter values are great additions. Proxies sound good as well.

On Maps, the concept is nice but not very useful unless you can do things like


    obj.set('some.deep.nested.value', {
        'more': {
            'nested': {
                'stuff': 'here'

On Observer again the concept is absolutely great but I wonder if the changes propagate:

    let obj = {
        'some': {
            'deep': {
                'nested': {
                    'value': true

    Object.observe(obj, function(changes){

    obj.some.deep.nested.value = false 
Will the observer be triggered for all changed properties (some, deep, nested, and value) or just the last one (value)?

For me Maps and Observers are highly important and it seems that no existing open source JS library/framework has implemented them in a way that makes sense.

Has anyone tried implementing these in such a way?

The goal of the Map feature is to create a primitive to JavaScript that does not exist today and cannot be efficiently emulated.

In particular, it allows the use of arbitrary, non-string keys. Objects (commonly used as Maps) can have only String keys.

In contrast, desiring a way to `get` a nested String value is easily emulated in terms of current JavaScript semantics. In Ember, for example, obj.get('some.nested.path') works in all browsers because it does not require any new primitives.

Observers are a similar story. `Object.observe` adds a new primitive to the language: the ability to receive asynchronous notifications about changes made to some object. On top of that, it is possible to implement semantics for nested objects and "computed properties".

The Ember team has already been exploring how to incorporate Object.observe into Ember's observer system when it is more broadly available. We support observing nested paths, and the Object.observe primitive gives us enough to build what we need on top.

You can expect that if certain patterns on top of these primitives become popular, TC39 will consider them in future versions of the specification.

Solutions to this problem are more common than you've found. Most recently released is Steeltoe [1], and there are previous examples (with varying features) noted in the Steeltoe reddit discussion [2].

[1] https://github.com/jclem/steeltoe

[2] http://www.reddit.com/r/javascript/comments/13cuxh/steeltoe_...

I remember seeing steeltoe on reddit. I like the fact that it's simple and does its job. Care to share any more?

I think we'll start seeing a lot of ES6 to ES5 compilers.

Then it's going to be a question of how to load the appropriate logic into the web page based on what it can do.

I have mixed feelings about this one, but I'm definitely looking forward to the new features.

You can't compile everything down: most notably, you cannot implement WeakMap without altering the GC.

It's not even clear how to fully implement things like class-side inheritance in a transpiler. The CoffeeScript implementation uses a definition-time copy of properties, which is probably good enough for many cases, but not all.

That said, many of the features are sugar around existing patterns, like rest and default parameters to functions or arrow functions, so I expect that even an incomplete transpiler would be broadly useful as the specification solidifies.

To every one here saying that we'll not see these features because we have to support IE and we have to wait till IE 11... well IE10 has automatic updates, and what does this has to do with ES.next?

A lot of features cannot shimmed in old FFs and V8s and JSC too, to those browsers' users we'd say "oh, come on! upgrade!".

We're talking about JS itself. Cannot wait to see the awesome improvements brought by ES6 used in SSJS.

BTW: does anybody know why they didn't put in the specs the Executable Class Body thing? It's the coolest part of Coffee-script, and it's the only real meta-programming style for class (IMHO).

> BTW: does anybody know why they didn't put in the specs the Executable Class Body thing? It's the coolest part of Coffee-script, and it's the only real meta-programming style for class (IMHO).

In an effort to get a class syntax into the spec, members of TC39 advocating for classes intentionally pared down their ambitions to something that could get a consensus of the members. Given the time-frame for ES6, I am happy that this proposal was accepted, because it gives us a base to work off of.

As a Rubyist, I consider "executable class bodies" or something like them to be crucial for user-land declarative syntax. I plan to do some work in the near-future on a proposal that should address this use-case.

Thank you, I believe that _crucial_ is the perfect adjective for this feature. As far as you know, is it going to be in the finalized ES6?

As I said, the class feature in ES6 was intentionally pared down to achieve consensus. I hope that something will make it into ES7.

Browsers do not need to wait for a spec to be fully finalized before starting to implement features. Firefox and Chrome have already started to implement large swaths of the more locked down parts of ES6.

Object.observe is actually a feature approved for ES7, and Chrome has already begun implementation. I tend not to think about the precise spec version that a feature is a part of, and more about getting consensus in the committee that a feature should be part of JavaScript period.

Perfect. That also means that we'll have to stick with sweetjs ATM to implement a slightly different class sugar.

Perfectly fine for me.

The problem with WeakMaps is that their keys are weak, not the values.

While weak keys are useful to provide a place to store extra data about an object, a more useful ability would be to have weak values, so you could find existing objects by string key, if they haven't been GC'd yet.

One big potential use for weak values is in ORMs. When asking for an object with id 5, if one exists you'd like the existing instance. However, you don't want the ORM keeping strong references to all of the instances, preventing them from ever being GC'd if nothing else is using them.

WeakMaps are useful for storing auxiliary information without having to pollute third-party objects and without impacting the ability to collect those objects.

For example, jQuery stores information on a unique, generated key on DOM nodes. Ember does something similar for meta-information about an object. With WeakMaps, both could store the information in a WeakMap, and avoid polluting the object.

WeakMaps are easier to get into the language because the GC-related semantics are unobservable. If you have a key you can use in `get`, the key is by definition not collectible. For reasons involving security leaks, it is more tricky (but not impossible) to add features to the language that allow third-parties to observe when an object is collected.

That said, I am personally a strong advocate for Weak References in the language, and have been advocating their inclusion on TC39. Two open proposals are http://wiki.ecmascript.org/doku.php?id=strawman:weak_referen... and http://wiki.ecmascript.org/doku.php?id=strawman:weak_refs. Active discussions involve post-mortem-finalization and avoiding security leaks.

As the maintainer of Ember and Ember Data, I fully agree with the need for this feature and will continue to work towards including it in the language.

A drawback of standard weak references is that it exposes garbage collector scheduling to the program, which would make JS programs more nondeterministic. I believe that historically nondeterminism like this has been a source of incompatibility between JS implementations.

The current proposals avoid this problem by requiring that objects held by weak references can only be observably collected between turns of the event loop.

In short: whenever a WeakReference is dereferenced, a temporary strong reference to the object is created that is dropped at the end of the turn of the event loop.

There might still be non-determinism, but it is limited to the type that is already common in JS. Behavior across event turns (i.e. happening in asynchronous callbacks) cannot make any assumptions about what else may have happened between callback registration and callback execution.

The values are held weakly in ES6 weak maps.

While these features are nice, they doesn't really enable us to do anything we couldn't do already. What I'd like to see are features that would actually make javascript more useful for developing apps, such as an ability to dispatch events while in a loop, or an API for screengrabbing.

> such as an ability to dispatch events while in a loop

Not sure I understand that one, what's the problem with dispatching events while in a loop?

> or an API for screengrabbing.

That makes absolutely no sense as part of ECMAScript.

The problem is that while in a loop, the browser's event loop is not fired. You have to use setTimeout and break out of the loop. Sometimes it's not feasible to use setTimeout for various reasons, and sometimes the browser chugs along even when you do use setTimeout. Javascript is the only platform that doesn't permit you to spin the event loop (technically Android doesn't let you do it, but there are hacks which work nicely). I've just had to put a project on hold due to this (basically porting a C++ web conferencing platform to javascript using emscripten).

Screengrabbing does make sense, and is required for web conferencing. All other features are there (audio/video/canvas), screengrabbing is the only one missing.

We're talking about Javascript the language, not individual implementations of javascript in browsers. Any browser could implement screengrab API today, they just haven't. Same for multithreaded javascript. Audio/video/canvas are all things that browsers have implemented, they are not innate features of Javascript.

Also despite what you say you CAN trigger an event (or whatever) inside a loop, it just won't do anything until you're out of the loop. This is because your browser implements javascript in a single thread. There are two easy solutions: Don't use a loop that's going to last for a long time, or use a Web Worker. This is, again, something that browsers have implemented, not a part of javascript. http://en.wikipedia.org/wiki/Web_worker

I didn't mean 'trigger an event', I meant 'spin the event loop'. Unfortunately web workers have too many limitations, and won't work in many situations. And the solution of 'don't use a loop' isn't possible/feasible in certain cases. No point in going into detail here, but basically I am porting a virtual machine to javascript.

> The problem is that while in a loop, the browser's event loop is not fired.

So by "the event loop is not fired" you mean "the event loop does not run" when you're already being run by the event loop? That seems to be... logical.

> You have to use setTimeout and break out of the loop.

You can also use e.g. window.postMessage. but yes to make the event loop run you do indeed have to yield to the event loop.

> and sometimes the browser chugs along even when you do use setTimeout.

Again, I'm not exactly clear on what you mean. Javascript has a toplevel event loop and a queue of fired events, when you yield to the event loops it runs the event queue in order, not sure what's surprising about this.

Hell, I'm not even sure this discussion makes sense as part of ECMAScript comments either, the event loop is not part of ECMAScript and it's perfectly possible to have JS runtimes with no event loops (the tracemonkey console for instance)

> Screengrabbing does make sense, and is required for web conferencing. All other features are there (audio/video/canvas), screengrabbing is the only one missing.

Reading comprehension. It happens to be a thing.

I didn't say screengrabbing made no sense, I said it made no sense as part of ECMAscript. It might make sense as part of WebRTC or as part of some DOM API, as part of ECMAScript it does not make any.

Very nice additions.

However, I wonder how long it'll take till we can actively use them in production code...

That depends on you. From the article:

    Alternatively, many ES.next features can be experimented with using Google's
    Traceur transpiler (useful unit tests with examples here) and there are shims
    available for other features via projects such as ES6-Shim and Harmony
There's also another quite comprehensive ES6 transpiler named six: https://github.com/matthewrobb/six

no it depends on browser vendors. Transpilers dont make generators or proxies magically works in ES5.

Same thing here, specially having to support IE all the time. :(

Same thing here :(

The compatibility table is here: http://kangax.github.com/es5-compat-table/es6/

Result: IE10 supports exactly zero of these features. We can start using them (maybe) once IE10 is dead.

Shhhhh Microsoft doesn't read the web.... they were completely unaware that ES6 was coming. The same way they were with HTML5 and much of CSS3. If only their employees were allowed to surf the net and see what cool stuff is being invented. Oh well, off to work on my cool ActiveX/VML Flash Shim....

Microsoft has a representative on TC39 (Luke Hoban) who is extremely active. In fact, I usually find that my thoughts on some new feature closely align with his.

Because Microsoft has bet on JavaScript heavily for Windows 8 apps (at least for now), and Windows 8 apps have full support for ES5, they have very good insights about ES5.

ES6 is still "coming". Many features are still in flux, and I don't blame Microsoft for not committing to in-flux ES6 features in the timeline of IE10.

I doubt we will ever get to use them, unless Windows 8 turns out to be such a clusterfuck that it takes Microsoft down with it.

IE9 still can't draw stroked text, for example.

The module syntax and local relabeling reminds me of module syntax in PLT/Racket a couple years back. Given JavaScript's heavy scheme influence to begin with, it seems like a good thing to me.

Hopefully the browser vendors get this implemented before MS start work on IE11. That's the only way we're going to be able to use this anytime soon.

Did you miss all the little notes about various features being already implemented in browsers?

like proxies and generators already implemented in IE8 ? we wont be using ES6 on the client until 2017 for sure.

Applications are open for YC Winter 2020

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact