JavaScript 2021 (ES12)
New features and improvements in ECMAScript 2021
🚀 What's New in JavaScript 2021?
JavaScript 2021 (ES12) introduced several powerful features including logical assignment operators, numeric separators, and Promise.any(). These features make code more readable and efficient.
// New in 2021: Logical Assignment Operators
let user = { name: 'John' };
user.name ||= 'Anonymous'; // Only assign if falsy
console.log(user.name); // 'John'
Key Features of ES12
Logical Assignment
Combine logical operators with assignment
x ||= y; // x = x || y
x &&= y; // x = x && y
x ??= y; // x = x ?? y
Numeric Separators
Make large numbers more readable
const million = 1_000_000;
const binary = 0b1010_0001;
Promise.any()
Resolve with first successful promise
Promise.any([p1, p2, p3])
.then(result => console.log(result));
Private Methods
True private class methods
class MyClass {
#privateMethod() {
return 'secret';
}
}
🔹 Logical Assignment Operators
Simplify common assignment patterns:
// Before ES12
let config = {};
if (!config.theme) {
config.theme = 'dark';
}
// ES12 way - much cleaner!
let config = {};
config.theme ||= 'dark'; // Only assign if falsy
// More examples
let user = { points: 0 };
user.points ||= 100; // user.points = 100
user.isActive &&= true; // Only if user.isActive exists
user.name ??= 'Guest'; // Only if null or undefined
console.log(user); // { points: 100, name: 'Guest' }
Output:
{ points: 100, name: 'Guest' }
🔹 Numeric Separators
Make large numbers easier to read:
// Hard to read
const population = 7800000000;
const fileSize = 1073741824;
// Easy to read with separators
const population = 7_800_000_000;
const fileSize = 1_073_741_824;
// Works with different number formats
const binary = 0b1010_0001_1000_0101;
const hex = 0xFF_EC_DE_5E;
const bigInt = 123_456n;
const decimal = 123.456_789;
console.log(population); // 7800000000 (separators are ignored)
Output:
7800000000
🔹 Promise.any()
Get the first successful promise result:
// Simulate different API calls
const fastAPI = new Promise(resolve =>
setTimeout(() => resolve('Fast API result'), 100)
);
const slowAPI = new Promise(resolve =>
setTimeout(() => resolve('Slow API result'), 500)
);
const failingAPI = new Promise((resolve, reject) =>
setTimeout(() => reject('API failed'), 50)
);
// Promise.any() returns the first successful result
Promise.any([failingAPI, fastAPI, slowAPI])
.then(result => {
console.log('First success:', result);
// Output: "First success: Fast API result"
})
.catch(error => {
console.log('All failed:', error);
});
Output:
First success: Fast API result
🔹 Private Class Methods
True privacy in JavaScript classes:
class BankAccount {
#balance = 0;
// Private method - cannot be called from outside
#validateAmount(amount) {
return amount > 0 && typeof amount === 'number';
}
// Private method for internal calculations
#calculateInterest() {
return this.#balance * 0.05;
}
// Public methods
deposit(amount) {
if (this.#validateAmount(amount)) {
this.#balance += amount;
return `Deposited $${amount}`;
}
return 'Invalid amount';
}
getBalance() {
return this.#balance + this.#calculateInterest();
}
}
const account = new BankAccount();
console.log(account.deposit(100)); // "Deposited $100"
console.log(account.getBalance()); // 105 (with interest)
// These would throw errors:
// account.#balance; // SyntaxError
// account.#validateAmount(50); // SyntaxError
Output:
Deposited $100 105
🔹 String.prototype.replaceAll()
Replace all occurrences without regex:
// Before ES12 - using regex or split/join
let text = "Hello world, wonderful world!";
let oldWay = text.replace(/world/g, 'universe');
// ES12 way - much simpler!
let newWay = text.replaceAll('world', 'universe');
console.log(newWay); // "Hello universe, wonderful universe!"
// Works with special characters too (no escaping needed)
let code = "let x = 5; let y = 10; let z = x + y;";
let updated = code.replaceAll('let', 'const');
console.log(updated); // "const x = 5; const y = 10; const z = x + y;"
Output:
Hello universe, wonderful universe! const x = 5; const y = 10; const z = x + y;