ES6 (ECMAScript 2015) added a batch of features that modern JavaScript relies on. The main ones: arrow functions, classes, template literals, destructuring, and more.
Arrow functions: a shorter syntax
Arrow functions give you a shorter way to write functions. They also handle this differently from traditional functions.
Traditional function:
function sum(a, b) {
return a + b;
}
Arrow function:
const sum = (a, b) => a + b;
Arrow functions suit short, single-operation functions. They do not bind their own this, so they are useful when you need to keep this from the surrounding scope.
Classes: syntactic sugar for prototypes
ES6 added a class syntax for object constructors and prototypes. Under the hood it is still prototype-based inheritance, but the code reads more clearly.
ES5 prototype:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.greet = function() {
return "Hello, my name is " + this.name;
};
ES6 class:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `Hello, my name is ${this.name}`;
}
}
Template literals: enhanced string handling
Template literals make multi-line strings and string interpolation straightforward.
Example – template literals:
const name = "Alice";
const greeting = `Hello, my name is ${name}`;
console.log(greeting); // Outputs: Hello, my name is Alice
They use backticks (`) instead of single or double quotes, and can span multiple lines – handy for HTML snippets or longer strings.
Destructuring: easier data access
Destructuring pulls values out of arrays or objects into separate variables.
Array destructuring:
const [first, second] = [10, 20];
console.log(first); // Outputs: 10
Object destructuring:
const {name, age} = {name: "Alice", age: 25};
console.log(name); // Outputs: Alice
Destructuring is particularly useful for function parameters.
Enhanced object literals
ES6 lets you define object properties and methods more concisely, including computed property names.
Example – enhanced object literals:
const name = "Alice";
const person = {
name,
greet() {
return `Hello, my name is ${this.name}`;
}
};
console.log(person.greet()); // Outputs: Hello, my name is Alice
Spread operator and rest parameters
The spread operator (...) expands an iterable like an array where multiple arguments or elements are expected. Rest parameters do the reverse – they gather arguments into an array.
Spread operator:
let parts = ['shoulders', 'knees'];
let body = ['head', ...parts, 'toes'];
console.log(body); // Outputs: ["head", "shoulders", "knees", "toes"]
Rest parameters:
function sum(...numbers) {
return numbers.reduce((acc, current) => acc + current, 0);
}
console.log(sum(1, 2, 3)); // Outputs: 6
Let and const: block scope variables
ES6 introduced let and const for block-scoped variables. var is function-scoped, which causes problems more often than you would expect.
let– for variables whose value can change.const– for variables that should not be reassigned.
Example:
let a = 10;
const b = 'hello';
These features are now standard in JavaScript. Arrow functions, classes, template literals, and destructuring turn up in most modern codebases – worth getting comfortable with.

