The next version of JavaScript—ES6, or ECMAScript 2015 as it'll officially be called—is taking shape. Finalization is expected next year, but transpilers like Traceur let us use features today. The question is: which features are stable enough to bet on, and which might change?
The Transpiler Bet
Using ES6 today means adding a build step. Traceur compiles ES6 to ES5 that browsers understand:
// ES6 code you write
class User {
constructor(name) {
this.name = name;
}
}
// ES5 code browsers run
var User = function User(name) {
this.name = name;
};
This adds complexity—another build tool, another layer between source and runtime, another place for bugs. But it lets teams explore ES6 patterns before browsers implement them.
The risk is betting on features that change. The ES6 spec isn't final. Features proposed today might be modified or dropped. Code written with today's understanding might not match tomorrow's standard.
Features That Feel Safe
Some ES6 features are unlikely to change significantly:
Arrow Functions
// Instead of
var double = function(x) { return x * 2; };
// Write
var double = x => x * 2;
Cleaner syntax for functions, and lexical this binding solves a common gotcha. This feels like obvious improvement.
Template Strings
var message = `Hello, ${name}!
Multiple lines work too.`;
String interpolation and multiline strings are basic features most languages have. JavaScript catching up here seems safe.
Destructuring
var {name, age} = user;
var [first, second] = array;
Pattern matching for assignment. This is in other languages and feels solid.
let and const
let x = 1; // block-scoped
const y = 2; // block-scoped, immutable binding
Block scoping instead of function scoping. Fixes one of JavaScript's weird parts.
These features are conceptually simple and similar to other languages. They're unlikely to change dramatically.
Features That Might Evolve
Other proposals are more complex and might see revision:
Classes
class Rectangle extends Shape {
constructor(width, height) {
super();
this.width = width;
}
area() {
return this.width * this.height;
}
}
Classes are syntactic sugar over prototypes. But the syntax and semantics are still being debated. The inheritance model, super behavior, and static methods all have edge cases being worked out.
Modules
import {foo, bar} from 'module';
export default MyClass;
Module syntax looks clean, but the loading semantics are complex. How modules map to files, how circular dependencies work, what the runtime loader API looks like—these are still being figured out.
Promises (Built-in)
fetch('/api/user')
.then(response => response.json())
.then(data => console.log(data));
Promises are great, and libraries like Q and when.js have proven the pattern. But the built-in API is still being refined. Details like error handling and cancellation are tricky.
Generators
function* fibonacci() {
let [a, b] = [0, 1];
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
Generators enable powerful patterns (async/await is built on them), but they're complex. The syntax and semantics might evolve as usage patterns emerge.
The Adoption Timeline Question
Even once ES6 is finalized, browser implementation will take time. Not all users update browsers quickly. Supporting older browsers means either:
- Continuing to transpile
- Writing ES5 indefinitely
- Dropping old browser support
This makes ES6 adoption a years-long transition, not a switch flip. Features we learn today might not run natively for 3-5 years.
Is it worth learning features you'll transpile away for years? Maybe. Understanding where the language is going helps write better code today. But the learning investment should be deliberate.
The Transpiler Performance Question
Transpiled ES6 isn't always as fast as hand-written ES5. Classes compile to more code than constructor functions. Generators require runtime support libraries. Features that look simple can have non-obvious performance costs.
For most applications, this doesn't matter—developer productivity trumps micro-optimizations. But for performance-critical code, transpiler output needs scrutiny.
Which Features to Learn Now
My take on which features justify immediate attention:
Learn now:
- Arrow functions (clear improvement)
- Template strings (obvious use cases)
- let/const (fixes real problems)
- Destructuring (common pattern)
- Default parameters (simple, useful)
Learn but don't rely on yet:
- Classes (still evolving)
- Promises (standardizing, but libraries work)
- Modules (syntax is nice, but loading semantics unclear)
Wait and see:
- Generators (powerful but complex)
- Symbols (niche use cases)
- Proxies (interesting but experimental)
- Tail call optimization (unclear implementation)
The Babel Factor
Traceur isn't the only transpiler. Projects like Babel are emerging with different trade-offs—smaller output, better readability, incremental feature adoption. The transpiler landscape is young.
Betting on a specific transpiler means accepting that your build tooling might change. Features might compile differently as transpilers mature. This is infrastructure risk.
Looking Forward
ES6 will change how we write JavaScript, but the transition is measured in years, not months. Learning features now provides advantage, but pragmatism suggests focusing on stable, high-value improvements.
The arrow functions and template strings of ES6 are immediately useful. The more complex features—modules, generators, proxies—are interesting but require deeper commitment to new patterns.
My approach: use the simple features that improve readability today, transpile them to ES5, and wait on complex features until the spec stabilizes and patterns emerge from early adopters.
The goal isn't being first with ES6. It's writing better code. Sometimes that means new features. Sometimes it means sticking with what works.
Resources:
- ES6 Compatibility Table – Browser and transpiler support
- Traceur – Google's ES6 transpiler
- ES6 Draft Spec – Latest specification
- Exploring ES6 – Book on ES6 features (work in progress)