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;

🧠 Test Your Knowledge

Which operator assigns a value only if the variable is falsy?