Key Differences Between Old JavaScript and ES6
ES6 (ECMAScript 2015) introduced a wide array of new features that significantly modernized JavaScript. These features improved syntax, readability, modularity, and introduced new capabilities like arrow functions, classes, and promises. Below is a summary of the most important ES6 features, along with examples and how they differ from "old" (pre-ES6) JavaScript.
1. let
and const
- Before ES6: Variables were declared using
var
, which is function-scoped and has hoisting issues. - ES6: Introduced
let
andconst
for block-scoped variables.let
: Mutable variable with block scope.const
: Immutable variable (its reference cannot be reassigned).
Example:
// Pre-ES6: var is function-scoped
var a = 10;
if (true) {
var a = 20;
console.log(a); // 20 (scope leaks outside the block)
}
console.log(a); // 20
// ES6: let is block-scoped
let b = 10;
if (true) {
let b = 20;
console.log(b); // 20 (b is block-scoped)
}
console.log(b); // 10 (no scope leak)
2. Arrow Functions (=>
)
- Before ES6: Functions were defined using the
function
keyword. - ES6: Introduced arrow functions with a shorter syntax and lexically bound
this
.
Example:
// Pre-ES6: Function expression
var add = function(a, b) {
return a + b;
};
// ES6: Arrow function
const add = (a, b) => a + b;
// Lexical `this` in arrow functions
const obj = {
name: "Alice",
sayName: function() {
setTimeout(function() {
console.log(this.name); // Undefined, `this` is not bound
}, 1000);
}
};
// Using arrow function binds `this` lexically
const obj2 = {
name: "Bob",
sayName: function() {
setTimeout(() => {
console.log(this.name); // Bob, because arrow functions inherit `this`
}, 1000);
}
};
3. Template Literals (` `
)
- Before ES6: String concatenation was done using
+
. - ES6: Introduced template literals for easier string interpolation, multiline strings, and embedded expressions.
Example:
// Pre-ES6: String concatenation
var name = "Alice";
var greeting = "Hello, " + name + "!";
// ES6: Template literals
const name = "Alice";
const greeting = `Hello, ${name}!`;
// Multiline string
const longString = `
This is a
multiline string.
`;
4. Destructuring Assignment
- Before ES6: Manually extracting properties from objects and arrays.
- ES6: Destructuring simplifies extracting values from arrays and objects.
Example:
// Pre-ES6: Manual extraction
var person = { name: "Alice", age: 25 };
var name = person.name;
var age = person.age;
// ES6: Destructuring
const { name, age } = person;
// Array destructuring
const arr = [1, 2, 3];
const [first, second] = arr;
5. Default Parameters
- Before ES6: Default values were set manually using conditionals.
- ES6: Allows default values for function parameters directly in the function signature.
Example:
// Pre-ES6: Default parameters with conditionals
function greet(name) {
var name = name || "Guest";
console.log("Hello, " + name);
}
// ES6: Default parameters
const greet = (name = "Guest") => console.log(`Hello, ${name}`);
6. Rest and Spread Operators (...
)
- Before ES6: Handling variable numbers of arguments or copying arrays required manual loops or
apply
. - ES6: Introduced the rest (
...args
) and spread (...array
) operators.- Rest: Gathers remaining function arguments into an array.
- Spread: Spreads an array or object into individual elements.
Example:
// Rest operator (collect arguments)
function sum(...numbers) {
return numbers.reduce((acc, val) => acc + val, 0);
}
// Spread operator (split array)
const arr = [1, 2, 3];
const newArr = [...arr, 4, 5]; // [1, 2, 3, 4, 5]
7. Classes
- Before ES6: Inheritance and object creation were handled through prototype chains and constructor functions.
- ES6: Introduced
class
syntax for creating object-oriented structures more cleanly.class
: A new way to declare classes.extends
: Allows inheritance.super()
: Calls the parent class constructor.
Example:
// Pre-ES6: Constructor functions
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(`${this.name} makes a sound.`);
};
// ES6: Class syntax
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a sound.`);
}
}
// Inheritance
class Dog extends Animal {
speak() {
console.log(`${this.name} barks.`);
}
}
8. Modules (import
/export
)
- Before ES6: JavaScript did not have native module support. Modules were implemented via third-party libraries like CommonJS (
require
/module.exports
). - ES6: Introduced native module syntax with
import
andexport
.
Example:
// In myModule.js
export const greet = () => console.log("Hello!");
// In main.js
import { greet } from './myModule.js';
greet(); // Hello!
9. Promises
- Before ES6: Asynchronous code was often written using callbacks, which led to "callback hell."
- ES6: Introduced Promises, which simplify asynchronous operations and chaining.
Example:
// Pre-ES6: Callback-based async code
setTimeout(function() {
console.log("Done!");
}, 1000);
// ES6: Promise-based async code
const wait = new Promise((resolve, reject) => {
setTimeout(() => resolve("Done!"), 1000);
});
wait.then((message) => console.log(message)); // Done!
10. Map
and Set
Data Structures
- Before ES6: JavaScript had limited built-in data structures, mainly objects and arrays.
- ES6: Introduced
Map
(key-value pairs) andSet
(unique values) as native data structures.
Example:
// Set example
const set = new Set([1, 2, 3, 3]);
console.log(set); // Set { 1, 2, 3 }
// Map example
const map = new Map();
map.set('key1', 'value1');
console.log(map.get('key1')); // value1
11. Enhanced Object Literals
- Before ES6: Object literals had verbose syntax.
- ES6: Enhanced object literals with shorthand properties and methods.
Example:
const name = "Alice";
const age = 25;
// Pre-ES6: Verbose object properties
var person = {
name: name,
age: age,
greet: function() {
return "Hello!";
}
};
// ES6: Shorthand properties and methods
const person = {
name,
age,
greet() {
return "Hello!";
}
};
12. for...of
Loop
- Before ES6: Iterating over arrays required
for
loops orforEach
. - ES6: Introduced
for...of
for easier iteration over arrays and iterable objects.
Example:
const arr = [10, 20, 30];
// Pre-ES6: forEach loop
arr.forEach(function(value) {
console.log(value);
});
// ES6: for...of loop
for (const value of arr) {
console.log(value);
}
Key Differences Between Old JavaScript and ES6:
- Scope Handling:
var
vs. block-scopedlet
andconst
. - Functions: ES6 arrow functions offer shorter syntax and lexically bound
this
. - String Handling: Template literals simplify string interpolation and multiline strings.
- Modularity: ES6 introduced native
import
/export
, while older JavaScript relied on third-party libraries. - Asynchronous Programming: Promises simplify handling asynchronous code compared to callback hell.
- OOP Syntax:
class
andextends
offer a more intuitive object-oriented syntax over prototype-based inheritance.