ECMAScript 2021, or JavaScript ES12, introduced a set of small but powerful features that improve developer experience, especially in areas like string manipulation, object handling, Promise debugging, and logical operations.
In this tutorial, you’ll learn:
- Overview of ES12
- Key features with examples
- A code model project using ES12 features
🔍 What’s New in ES12 (2021)?
The ES12 update includes:
- Logical Assignment Operators (
||=
,&&=
,??=
) - Numeric Separators
String.prototype.replaceAll()
- Promise
any()
WeakRef
andFinalizationRegistry
Object.hasOwn()
Let’s break them down.
1. ✅ Logical Assignment Operators (||=
, &&=
, ??=
)
These are shorthand ways of combining logic and assignment.
🧪 Examples:
javascriptCopyEditlet name = null;
name ||= "Guest"; // name = "Guest"
let count = 5;
count &&= 10; // count = 10
let title = undefined;
title ??= "Untitled"; // title = "Untitled"
This simplifies conditionally setting variables.
2. 🔢 Numeric Separators (_
)
You can use underscores (_
) to make large numbers more readable.
javascriptCopyEditconst billion = 1_000_000_000;
console.log(billion); // 1000000000
This does not affect the value—just the readability.
3. 🔁 String.prototype.replaceAll()
Replaces all instances of a substring without needing regex with global flag.
javascriptCopyEditconst text = "apple, banana, apple";
const updated = text.replaceAll("apple", "orange");
console.log(updated); // "orange, banana, orange"
This is more intuitive than using text.replace(/apple/g, 'orange')
.
4. 🔂 Promise.any()
Returns the first fulfilled promise. If all reject, it returns an AggregateError
.
javascriptCopyEditconst p1 = Promise.reject("Fail 1");
const p2 = Promise.resolve("Success");
const p3 = Promise.reject("Fail 2");
Promise.any([p1, p2, p3]).then(result => {
console.log(result); // "Success"
});
Perfect when you want any successful result from multiple sources.
5. 🧼 Object.hasOwn()
(Better than hasOwnProperty()
)
Checks if an object has a direct property of its own.
javascriptCopyEditconst user = { name: "Alice" };
console.log(Object.hasOwn(user, "name")); // true
It’s more reliable than using hasOwnProperty
because it works even if the object doesn’t inherit from Object.prototype
.
6. 🧠 WeakRef and FinalizationRegistry (Advanced)
These deal with memory management and garbage collection.
javascriptCopyEditlet obj = { name: "data" };
let ref = new WeakRef(obj);
// Later: you can dereference the weak reference
console.log(ref.deref()); // { name: "data" }
Useful for building caches or observers, but not often needed in everyday projects.
🛠 Code Model: Post Processor Tool
🎯 Objective:
- Set default metadata with logical assignment
- Replace all keywords in post content
- Check if post has certain data
- Format large view counts
- Resolve any available translations using
Promise.any()
✅ ES12 Code Example:
javascriptCopyEdit// Initial post object
let post = {
title: undefined,
content: "Learn JS. JS is fun!",
views: 25_000,
tags: null,
};
// Logical assignment to set defaults
post.title ??= "Untitled Post";
post.tags ||= ["javascript", "tutorial"];
// Replace all mentions of "JS" with "JavaScript"
post.content = post.content.replaceAll("JS", "JavaScript");
// Display view count using numeric separator
console.log(`Views: ${post.views}`);
// Check if property exists
if (Object.hasOwn(post, "title")) {
console.log("Title exists:", post.title);
}
// Simulate translations loading
const en = Promise.reject("No English");
const es = Promise.resolve("Artículo en Español");
const fr = Promise.reject("Aucun Français");
Promise.any([en, es, fr])
.then(translation => {
console.log("Translation loaded:", translation);
})
.catch(error => {
console.log("No translations available:", error);
});
🖥 Output:
yamlCopyEditViews: 25000
Title exists: Untitled Post
Translation loaded: Artículo en Español
This project uses:
??=
,||=
for safe default valuesreplaceAll()
for content replacementObject.hasOwn()
for safety checkingPromise.any()
for loading available translations25_000
for improved readability with numeric separators
🧠 Summary Table
Feature | Description | Example |
---|---|---|
??= , ` | =, &&=` | |
Numeric separators | Makes large numbers readable | 1_000_000 |
replaceAll() | Replace all substrings in a string | "a a".replaceAll("a", "b") |
Promise.any() | Returns first fulfilled Promise | Promise.any([...]) |
Object.hasOwn() | Checks direct object property | Object.hasOwn(obj, 'key') |
WeakRef | Weak reference to an object | new WeakRef(obj) |
✅ Conclusion
JavaScript ES12 (2021) focused on ergonomics — making common tasks easier, safer, and more readable. Whether you’re assigning default values, working with promises, or processing strings, these features simplify your code and reduce boilerplate.
Even if you’re a beginner, features like ??=
, replaceAll()
, and Promise.any()
are quick wins for writing cleaner, modern JavaScript.