ecmascript

es5 -> es6

// from var to let / const

// from IIFEs(immediately-invoked function expression) to blocks
(function () {  // open IIFE
    var tmp = ···;
    ···
}());  // close IIFE

console.log(tmp); // ReferenceError

{
    const temp = ''; 
}

// string interpolation `${x}`
// multi-line strings

// from function expressions to arrow functions

// descructing
const [, year, month, day] =
    /^(\d\d\d\d)-(\d\d)-(\d\d)$/
    .exec('2999-12-31');

// from for to forEach / for-of
for (const [index, elem] of arr.entries()) {
    console.log(index+'. '+elem);
}

// default parameters
function foo(x, y) {
    x = x || 0;
    y = y || 0;
    ···
}

function foo(x=0, y=0) { }

// named parameters
function selectEntries(options) {
    var start = options.start || 0;
    var end = options.end || -1;
    var step = options.step || 1;
    ···
}

function selectEntries({ start=0, end=-1, step=1 }) {
    ···
}

// make parameter optional
function selectEntries(options) {
    options = options || {}; // (A)
    var start = options.start || 0;
    var end = options.end || -1;
    var step = options.step || 1;
    ···
}

function selectEntries({ start=0, end=-1, step=1 } = {}) {
    ···
}

// from arguments to rest parameters
function logAllArguments() {
    for (var i=0; i < arguments.length; i++) {
        console.log(arguments[i]);
    }
}

function logAllArguments(...args) {
    for (const arg of args) {
        console.log(arg);
    }
}

function format(pattern) {
    var args = [].slice.call(arguments, 1);
    ···
}

function format(pattern, ...args) {
    ···
}

// from apply() to spread operator(...)
Math.max.apply(Math, [-1, 5, 11, 3])
11

Math.max(...[-1, 5, 11, 3])
11

var arr1 = ['a', 'b'];
var arr2 = ['c', 'd'];
arr1.push.apply(arr1, arr2);
    // arr1 is now ['a', 'b', 'c', 'd']

const arr1 = ['a', 'b'];
const arr2 = ['c', 'd'];
arr1.push(...arr2);
    // arr1 is now ['a', 'b', 'c', 'd']

// from concat to spread operator
var arr1 = ['a', 'b'];
var arr2 = ['c'];
var arr3 = ['d', 'e'];
console.log(arr1.concat(arr2, arr3));
    // [ 'a', 'b', 'c', 'd', 'e' ]

const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e'];
console.log([...arr1, ...arr2, ...arr3]);
    // [ 'a', 'b', 'c', 'd', 'e' ]

// from function expressions in object literals to method definitions
var obj = {
    foo: function () {
        ···
    },
    bar: function () {
        this.foo();
    }, // trailing comma is legal in ES5
}

const obj = {
    foo() {
        ···
    },
    bar() {
        this.foo();
    },
}

// from constructors to classes
function Person(name) {
    this.name = name;
}
Person.prototype.describe = function () {
    return 'Person called '+this.name;
};

class Person {
    constructor(name) {
        this.name = name;
    }
    describe() {
        return 'Person called '+this.name;
    }
}

// derived classes
function Employee(name, title) {
    Person.call(this, name); // super(name)
    this.title = title;
}
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;
Employee.prototype.describe = function () {
    return Person.prototype.describe.call(this) // super.describe()
           + ' (' + this.title + ')';
};

class Employee extends Person {
    constructor(name, title) {
        super(name);
        this.title = title;
    }
    describe() {
        return super.describe() + ' (' + this.title + ')';
    }
}

// from custom error constructors to subclasses of Error
function MyError() {
    // Use Error as a function
    var superInstance = Error.apply(null, arguments);
    copyOwnPropertiesFrom(this, superInstance);
}
MyError.prototype = Object.create(Error.prototype);
MyError.prototype.constructor = MyError;
function copyOwnPropertiesFrom(target, source) {
    Object.getOwnPropertyNames(source)
    .forEach(function(propKey) {
        var desc = Object.getOwnPropertyDescriptor(source, propKey);
        Object.defineProperty(target, propKey, desc);
    });
    return target;
};

class MyError extends Error {
}

// from objects to maps
var dict = Object.create(null);
function countWords(word) {
    var escapedWord = escapeKey(word);
    if (escapedWord in dict) {
        dict[escapedWord]++;
    } else {
        dict[escapedWord] = 1;
    }
}
function escapeKey(key) {
    if (key.indexOf('__proto__') === 0) {
        return key+'%';
    } else {
        return key;
    }
}

const map = new Map();
function countWords(word) {
    const count = map.get(word) || 0;
    map.set(word, count + 1);
}

// new string methods
// from indexOf to startsWith
if (str.indexOf('x') === 0) {} // ES5
if (str.startsWith('x')) {} // ES6

// from indexOf to includes
if (str.indexOf('x') >= 0) {} // ES5
if (str.includes('x')) {} // ES6

// from join to repeat
new Array(3+1).join('#') // ES5
'#'.repeat(3) // ES6

// new array methods
// from indexOf to findIndex
const arr = ['a', NaN];
arr.indexOf(NaN); // -1
arr.findIndex(x => Number.isNaN(x)); // 1 can find NaN

// from slice to from or the spread operator
var arr1 = Array.prototype.slice.call(arguments); // ES5
const arr2 = Array.from(arguments); // ES6

const arr1 = [...'abc'];
    // ['a', 'b', 'c']
const arr2 = [...new Set().add('a').add('b')];
    // ['a', 'b']

// from apply to fill
// Same as Array(undefined, undefined)
var arr1 = Array.apply(null, new Array(2));
    // [undefined, undefined]
const arr2 = new Array(2).fill(undefined);
    // [undefined, undefined]

// ES5
var arr3 = Array.apply(null, new Array(2))
    .map(function (x) { return 'x' });
    // ['x', 'x']

// ES6
const arr4 = new Array(2).fill('x');
    // ['x', 'x']