Những tính năng mới trong ECMAScript 2021 (ES12) JavaScript
JavaScript Versions | by
JavaScript là một trong những ngôn ngữ lập trình phổ biến nhất hiện nay, được sử dụng rộng rãi trong cả lập trình web frontend lẫn backend. Để đáp ứng nhu cầu ngày càng cao của các lập trình viên, ECMAScript – tiêu chuẩn của JavaScript – liên tục được cập nhật với những cải tiến quan trọng.
ECMAScript 2021 (ES12) đánh dấu một bước tiến mới trong việc tối ưu hóa cú pháp, cải thiện hiệu suất và quản lý bộ nhớ hiệu quả hơn. Những tính năng mới trong ES12 như Logical Assignment Operators (&&=, ||=, ??=), Promise.any(), String.replaceAll(), WeakRef, FinalizationRegistry không chỉ giúp lập trình viên viết code ngắn gọn hơn mà còn nâng cao khả năng xử lý dữ liệu.
Vậy ES12 có những thay đổi gì nổi bật? Hãy cùng tìm hiểu chi tiết về các tính năng mới và ứng dụng của chúng trong lập trình JavaScript hiện đại.
ECMAScript 2021 (ES12) là gì?
ECMAScript 2021 (ES12) là phiên bản mới của tiêu chuẩn ECMAScript, được phát hành vào năm 2021. Đây là một phần của quá trình cập nhật hàng năm của ECMAScript, giúp cải thiện ngôn ngữ JavaScript bằng cách bổ sung các tính năng mới, tối ưu hóa hiệu suất và làm cho cú pháp trở nên dễ hiểu hơn.
ES12 tiếp tục mang đến những cải tiến quan trọng giúp lập trình viên viết code ngắn gọn, dễ bảo trì và hiệu quả hơn. Một số tính năng nổi bật trong ES12 bao gồm:
- Logical Assignment Operators (
&&=
,||=
,??=
) – Hỗ trợ gán giá trị logic trực tiếp vào biến, giúp rút gọn code. Promise.any()
– Cho phép xử lý nhiều Promise đồng thời và trả về kết quả đầu tiên thành công.String.prototype.replaceAll()
– Giúp thay thế tất cả các chuỗi con mà không cần sử dụng biểu thức chính quy.- WeakRef (Tham chiếu yếu) & FinalizationRegistry – Cải thiện quản lý bộ nhớ trong JavaScript, đặc biệt hữu ích trong các ứng dụng lớn.
- Separators for Numeric Literals (Dấu gạch dưới trong số) – Hỗ trợ viết số dễ đọc hơn bằng cách sử dụng dấu
_
.
Tại sao ES12 quan trọng đối với lập trình JavaScript hiện đại?
Sự phát triển của JavaScript luôn gắn liền với nhu cầu của lập trình viên và các ứng dụng thực tế. ES12 mang lại nhiều lợi ích quan trọng giúp nâng cao trải nghiệm lập trình, bao gồm:
Giúp code ngắn gọn và dễ hiểu hơn
- Các toán tử gán logic (
&&=
,||=
,??=
) giúp giảm số dòng code và loại bỏ các câu lệnh if không cần thiết. String.prototype.replaceAll()
giúp đơn giản hóa việc thay thế chuỗi mà không cần dùng biểu thức chính quy phức tạp.
Cải thiện hiệu suất và trải nghiệm lập trình bất đồng bộ
Promise.any()
giúp xử lý nhiều tác vụ đồng thời mà không cần đợi tất cả Promise hoàn tất, hữu ích trong xử lý API hoặc tải dữ liệu.
Tăng khả năng quản lý bộ nhớ hiệu quả
- WeakRef & FinalizationRegistry hỗ trợ thu gom rác (garbage collection) tốt hơn, giúp giảm rò rỉ bộ nhớ trong các ứng dụng lớn.
Cú pháp dễ đọc hơn
- Dấu gạch dưới trong số (
1_000_000
) giúp làm việc với các con số lớn trở nên rõ ràng và trực quan hơn.
Với những tính năng quan trọng trên, ES12 giúp JavaScript trở thành một ngôn ngữ mạnh mẽ hơn, thân thiện hơn với lập trình viên và phù hợp với các ứng dụng hiện đại
Các tính năng mới trong ECMAScript 2021 (ES12) trong JavaScript
Logical Assignment Operators (&&=, ||=, ??=) – Toán tử gán logic
Trước ES12, khi muốn gán giá trị cho một biến dựa trên điều kiện logic, lập trình viên thường sử dụng các câu lệnh if
hoặc các biểu thức dài dòng. Với ES12, các toán tử gán logic (&&=
, ||=
, ??=
) giúp rút gọn và tối ưu hóa cú pháp.
&&=
(AND assignment): Chỉ gán giá trị mới nếu giá trị hiện tại không phảifalse
,0
,""
,null
,undefined
.||=
(OR assignment): Chỉ gán giá trị mới nếu giá trị hiện tại làfalse
,0
,""
,null
,undefined
.??=
(Nullish assignment): Chỉ gán giá trị mới nếu giá trị hiện tại lànull
hoặcundefined
.
Ví dụ sử dụng các toán tử gán logic:
let a = true; a &&= false; // a = false let b = null; b ||= "Giá trị mặc định"; // b = "Giá trị mặc định" let c = undefined; c ??= "Chỉ gán nếu null hoặc undefined"; // c = "Chỉ gán nếu null hoặc undefined"
- Giúp code ngắn gọn, dễ đọc hơn.
- Tránh các biểu thức
if
lồng nhau phức tạp. - Cải thiện hiệu suất khi xử lý điều kiện.
Numeric Separators (_) – Dễ đọc hơn khi làm việc với số lớn
Trong ES12, dấu gạch dưới (_
) có thể được sử dụng để phân tách các chữ số trong số lớn, giúp chúng dễ đọc hơn.
Trước ES12:
const num = 1000000000; // Khó đọc
Sau ES12:
const num = 1_000_000_000; // Dễ đọc hơn
Giúp làm việc với số lớn dễ dàng hơn.
Không ảnh hưởng đến giá trị thực của số.
Hữu ích khi làm việc với số điện thoại, mã số, giá trị tiền tệ, v.v.
String.prototype.replaceAll() – Thay thế tất cả chuỗi dễ dàng hơn
Trong các phiên bản trước của JavaScript, khi muốn thay thế tất cả các lần xuất hiện của một chuỗi con, lập trình viên thường phải sử dụng biểu thức chính quy với cờ g
(global
).
Trước ES12:
let text = "Hello world, world!"; console.log(text.replace("world", "JavaScript")); // "Hello JavaScript, world!"
Lệnh trên chỉ thay thế lần xuất hiện đầu tiên của "world"
. Nếu muốn thay thế tất cả, ta phải dùng RegEx:
console.log(text.replace(/world/g, "JavaScript")); // "Hello JavaScript, JavaScript!"
Sau ES12 (Sử dụng replaceAll()
)
console.log(text.replaceAll("world", "JavaScript")); // "Hello JavaScript, JavaScript!"
Cú pháp đơn giản, dễ hiểu hơn so với RegEx.
Tránh nhầm lẫn khi xử lý chuỗi không cần biểu thức chính quy.
Tăng hiệu suất trong xử lý chuỗi lớn.
Promise.any() – Hoạt động ngược với Promise.all()
Trước đây, Promise.all()
được sử dụng để đợi tất cả các Promise hoàn thành. Nếu bất kỳ Promise nào thất bại (reject
), toàn bộ Promise.all()
sẽ thất bại.
ES12 giới thiệu Promise.any()
, giúp trả về giá trị của Promise đầu tiên thành công, thay vì đợi tất cả.
Ví dụ so sánh Promise.all()
và Promise.any()
:
const p1 = new Promise((resolve, reject) => setTimeout(reject, 100, "Lỗi 1")); const p2 = new Promise((resolve) => setTimeout(resolve, 200, "Thành công 2")); const p3 = new Promise((resolve) => setTimeout(resolve, 300, "Thành công 3")); // Promise.all() sẽ thất bại nếu có ít nhất một lỗi Promise.all([p1, p2, p3]) .then(console.log) .catch((err) => console.log("Lỗi:", err)); // Promise.any() trả về kết quả đầu tiên thành công Promise.any([p1, p2, p3]) .then(console.log) // Kết quả: "Thành công 2" .catch((err) => console.log("Tất cả đều thất bại:", err));
Hữu ích khi chỉ cần một kết quả hợp lệ, thay vì đợi tất cả.
Tăng tốc độ xử lý khi làm việc với nhiều API.
WeakRef và FinalizationRegistry – Quản lý bộ nhớ tốt hơn
WeakRef (Tham chiếu yếu) giúp tạo một tham chiếu yếu đến object, cho phép hệ thống thu gom rác (Garbage Collection
) khi cần thiết mà không giữ lại đối tượng lâu hơn mức cần thiết.
Ví dụ sử dụng WeakRef
:
let user = { name: "Alice" }; const weakUser = new WeakRef(user); console.log(weakUser.deref()); // { name: "Alice" } user = null; // Object có thể bị thu gom rác
FinalizationRegistry giúp thực hiện hành động khi một object bị thu gom rác.
Ví dụ sử dụng FinalizationRegistry
:
const registry = new FinalizationRegistry((value) => { console.log(`Object đã bị xóa: ${value}`); }); let obj = { name: "Test" }; registry.register(obj, "Test Object"); obj = null; // Khi obj bị xóa, FinalizationRegistry sẽ gọi callback