ES6 (or ES2015, whatever we’re calling it now) has been out for a while, and with Babel, we can finally use it in production. Here are the features I use constantly.

Arrow Functions

This is probably the most visible change:

// Old way
var self = this;
setTimeout(function() {
    self.doSomething();
}, 1000);

// ES6 way
setTimeout(() => {
    this.doSomething();
}, 1000);

No more var self = this nonsense. Arrow functions lexically bind this, which is what you want 99% of the time.

Also, they’re just cleaner for simple functions:

// Old
var doubled = numbers.map(function(n) {
    return n * 2;
});

// ES6
const doubled = numbers.map(n => n * 2);

Let and Const

I’ve basically stopped using var. const for things that don’t change, let for things that do:

const API_URL = 'https://api.example.com';  // Won't change
let counter = 0;  // Will change

for (let i = 0; i < 10; i++) {
    // i is block-scoped, not function-scoped
}

Block scoping makes way more sense than function scoping. Fewer bugs from variable hoisting.

Template Literals

String concatenation is dead to me:

// Old
var message = 'Hello, ' + name + '! You have ' + count + ' messages.';

// ES6
const message = `Hello, ${name}! You have ${count} messages.`;

Multi-line strings are also way better:

const html = `
    <div class="card">
        <h2>${title}</h2>
        <p>${description}</p>
    </div>
`;

Destructuring

This one took me a bit to get used to, but now I love it:

// Array destructuring
const [first, second, ...rest] = [1, 2, 3, 4, 5];

// Object destructuring
const {name, age} = user;

// Function parameters
function greet({name, age}) {
    console.log(`${name} is ${age} years old`);
}

Super useful for React props:

// Instead of this
function UserCard(props) {
    return <div>{props.user.name}</div>;
}

// Do this
function UserCard({user: {name}}) {
    return <div>{name}</div>;
}

Default Parameters

No more param = param || defaultValue:

// Old
function greet(name) {
    name = name || 'Guest';
    console.log('Hello, ' + name);
}

// ES6
function greet(name = 'Guest') {
    console.log(`Hello, ${name}`);
}

Spread Operator

Copying arrays and objects is so much cleaner:

// Array spread
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5];  // [1, 2, 3, 4, 5]

// Object spread (stage 3 proposal, but Babel supports it)
const obj1 = {a: 1, b: 2};
const obj2 = {...obj1, c: 3};  // {a: 1, b: 2, c: 3}

Great for immutable updates:

// Instead of mutating
array.push(newItem);

// Create new array
const newArray = [...array, newItem];

Modules

Finally, a standard module system:

// math.js
export function add(a, b) {
    return a + b;
}

export const PI = 3.14159;

// app.js
import {add, PI} from './math';

No more AMD vs CommonJS debates. Well, we still have to use Webpack or Browserify to bundle, but at least the syntax is standard.

Classes

I know, I know, they’re just syntactic sugar over prototypes. But they’re nice sugar:

class User {
    constructor(name) {
        this.name = name;
    }
    
    greet() {
        return `Hello, ${this.name}`;
    }
}

class Admin extends User {
    constructor(name, level) {
        super(name);
        this.level = level;
    }
}

Much cleaner than the prototype chain mess.

Promises

Technically ES6, though we’ve been using libraries like Q and Bluebird for years:

fetch('/api/users')
    .then(response => response.json())
    .then(users => {
        console.log(users);
    })
    .catch(error => {
        console.error(error);
    });

Way better than callback hell. Can’t wait for async/await (coming in ES2017).

What I Don’t Use Much

  • Symbols: Haven’t found a use case yet
  • Generators: Interesting, but haven’t needed them
  • Proxies: Too slow for production
  • WeakMap/WeakSet: Niche use cases

Browser Support

We’re using Babel to transpile everything to ES5. Our babel config:

{
  "presets": ["es2015"],
  "plugins": ["transform-object-rest-spread"]
}

Works great. The transpiled code is a bit larger, but the developer experience is worth it.

Should You Use ES6?

If you’re starting a new project, absolutely. The tooling is mature enough now. We’ve been using it in production for 6 months with zero issues.

For existing projects, it depends. The migration can be gradual - Babel can handle a mix of ES5 and ES6. We migrated one file at a time.

The productivity boost is real. I’m way faster writing ES6 than ES5. The code is more readable and less error-prone.

If you haven’t tried ES6 yet, give it a shot. You won’t want to go back.