ES6 vs ES5: Key Features Comparison
ES6 was a monumental update that fundamentally transformed JavaScript from a simple scripting language into a robust language suitable for large-scale application development. It added syntactic sugar, new powerful features, and solved many common pain points of ES5.
1. Variable Declarations: let and const
ES5: Only var, which is function-scoped and prone to issues like accidental re-declaration and hoisting.
var x = 10;
var x = 20; // No error, just overwrites
ES6: Introduced block-scoped let and const. let for variables that can be reassigned. const for variables that should not be reassigned.
let name = "Alice";
name = "Bob"; // OK
const pi = 3.14159;
// pi = 3; // Error: Assignment to constant variable.
if (true) {
let blockScoped = "inside"; // Only exists in this block
}
// console.log(blockScoped); // Error: not defined
2. Arrow Functions =>
ES5: Verbose function syntax, especially for callbacks. The this keyword is dynamically scoped, leading to common workarounds.
var add = function(a, b) {
return a + b;
};
arr.map(function(x) { return x * 2; });
ES6: Concise syntax and lexically scoped this (it inherits this from the surrounding code). Perfect for short callbacks and methods.
const add = (a, b) => a + b;
arr.map(x => x * 2);
// Lexical 'this' - no more 'var self = this'
setTimeout(() => {
console.log(this.someValue); // 'this' is from the outer scope
}, 100);
3. Template Literals (Template Strings)
ES5: Cumbersome string concatenation.
var name = "Sarah";
var greeting = "Hello, " + name + "!\nWelcome to " + company + ".";
ES6: Use backticks ` and ${} for interpolation and multi-line strings.
const name = "Sarah";
const greeting = `Hello, ${name}!
Welcome to ${company}.`;
4. Destructuring Assignment
ES5: Extracting data from objects/arrays required repetitive code.
var user = {name: 'Alex', age: 30};
var userName = user.name;
var userAge = user.age;
var arr = [1, 2, 3];
var first = arr[0];
ES6: Extract data from arrays or objects into distinct variables using a syntax that mirrors their construction.
// Object Destructuring
const user = {name: 'Alex', age: 30};
const {name, age} = user; // Creates variables 'name' and 'age'
// Array Destructuring
const arr = [1, 2, 3];
const [first, second] = arr; // first = 1, second = 2
// Function Parameter Destructuring
function greet({name, age}) {
return `Hello ${name}, you are ${age}.`;
}
5. Default Parameters
ES5: Had to use logical OR (||) tricks to set defaults.
function greet(name) {
name = name || 'Guest';
}
ES6: Specify default values directly in the function signature.
function greet(name = 'Guest', age = 18) {
return `Hello ${name}`;
}
greet(); // "Hello Guest"
6. Enhanced Object Literals
ES5: Objects were more verbose to define.
var obj = {
prop: propValue,
method: function() { ... }
};
ES6: Shorthand for defining properties and methods.
const propValue = 10;
const obj = {
propValue, // Shorthand property (same as propValue: propValue)
method() { // Shorthand method (no 'function' keyword)
// ...
},
// Computed property names
[`prop_${42}`]: 'Life' // Property name is computed at runtime
};
7. Promises
ES5: Async operations used callbacks, leading to "callback hell" or deeply nested callbacks.
asyncFunction(arg, function(result) {
anotherAsyncFunction(result, function(newResult) {
// Callback hell
});
});
ES6: Introduced the Promise object for managing asynchronous operations. It provides a cleaner, chainable syntax for handling success and error cases.
asyncFunction(arg)
.then(result => anotherAsyncFunction(result))
.then(newResult => {
// Handle new result
})
.catch(error => {
// Handle any error in the chain
});
8. Classes
ES5: Used constructor functions and prototype inheritance, which was unfamiliar to developers from class-based languages.
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function() {
console.log(this.name);
};
ES6: Provides a much clearer and more familiar syntax for creating objects and dealing with inheritance (syntactic sugar over prototype-based inheritance).
class Person {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}
class Developer extends Person { // 'extends' for inheritance
constructor(name, language) {
super(name); // Call the parent constructor
this.language = language;
}
}
9. Modules: import / export
ES5: No native module system. Relied on libraries like RequireJS or CommonJS (Node.js).
// CommonJS (Node.js)
var lib = require('./lib');
module.exports = function() { ... };
ES6: Native support for modular code.
// lib.js - Exports
export const apiKey = '123abc';
export function sum(a, b) { return a + b; }
export default class User { ... } // Default export
// app.js - Imports
import User, { apiKey, sum } from './lib'; // Import default + named exports
Other Notable ES6 Features:
- Rest/Spread Operator (...): function(...args) collects arguments into an array. [...arr] spreads an array into elements.
- Iterators & for...of loop: A unified way to iterate over data structures (arrays, maps, strings).
- New Built-in Methods: Helpers like Array.prototype.find(), String.prototype.includes(), Object.assign().
- Map and Set Collections: Data structures for key/value pairs and unique values, respectively.
- Symbols: A new primitive type for creating unique property keys.
Conclusion
ES6 made JavaScript code more expressive, concise, and readable. It provided modern language constructs (classes, modules) and solved long-standing problems (scoping with let/const, this binding with arrow functions), paving the way for the modern JavaScript ecosystem.
Comments
Post a Comment