Những tính năng mới trong ECMAScript 2021 (ES12) JavaScript

JavaScript Versions | by Học Javascript

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ải false, 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ặc undefined.

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()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

Cải thiện hiệu suất bộ nhớ, tránh rò rỉ dữ liệu.
Hữu ích trong lập trình game, xử lý hình ảnh, AI, và các ứng dụng lớn.

Logical Operators in Optional Chaining (?., &&, ||, ??)

Trước đây, khi muốn truy cập một thuộc tính mà không chắc chắn object có tồn tại hay không, ta thường phải kiểm tra từng cấp:

Trước ES12:

if (obj && obj.user && obj.user.profile) {
  console.log(obj.user.profile.name);
}

Sau ES12 (Kết hợp Optional Chaining với toán tử logic):

console.log(obj?.user?.profile?.name || "Không có thông tin");
Giúp code ngắn gọn và dễ hiểu hơn.
Tránh lỗi Cannot read properties of undefined.

Ứng dụng của ES12 trong lập trình JavaScript

ECMAScript 2021 (ES12) mang lại nhiều cải tiến giúp code JavaScript ngắn gọn hơn, hiệu suất tốt hơndễ đọc hơn. Dưới đây là những ứng dụng quan trọng của ES12 trong lập trình JavaScript.

Giúp code ngắn gọn, dễ đọc hơn với toán tử gán logic và numeric separators

Toán tử gán logic (&&=, ||=, ??=)

Trước đây, khi muốn kiểm tra điều kiện trước khi gán giá trị cho một biến, ta phải sử dụng cú pháp dài dòng:

Trước ES12:

let value = null;
if (!value) {
  value = "Giá trị mặc định";
}

Sau ES12 (Viết ngắn gọn hơn với ||=):

let value = null;
value ||= "Giá trị mặc định"; // Nếu value là null/undefined/false/0, gán "Giá trị mặc định"
console.log(value); // "Giá trị mặc định"
  • Rút gọn cú pháp khi cập nhật giá trị biến.
  • Giảm lỗi cú pháp khi làm việc với dữ liệu có giá trị mặc định.
  • Hữu ích khi xử lý dữ liệu nhập vào từ form hoặc API.

Numeric Separators (_) – Dễ đọc hơn khi làm việc với số lớn

Trong ES12, dấu gạch dưới (_) giúp phân tách các chữ số trong số lớn, giúp lập trình viên đọc dễ dàng hơn.

Trước ES12:

const budget = 1000000000; // 1 tỷ, nhưng khó đọc

Sau ES12:

const budget = 1_000_000_000; // Dễ đọc hơn
console.log(budget); // 1000000000 (giữ nguyên giá trị)

Giúp lập trình viên dễ đọc và hiểu các số lớn trong tài chính, khoa học dữ liệu.
Hữu ích khi làm việc với số điện thoại, mã số tài khoản, ID, v.v.

Cải thiện hiệu suất với Promise.any() và quản lý bộ nhớ với WeakRef

Promise.any() – Cải thiện tốc độ xử lý bất đồng bộ

Trong JavaScript, khi làm việc với nhiều Promise, ta có thể sử dụng Promise.any() để lấy kết quả của Promise đầu tiên thành công, thay vì đợi tất cả hoặc thất bại nếu có một lỗi (như Promise.all()).

Ví dụ thực tế – Tải dữ liệu từ nhiều API và lấy kết quả nhanh nhất:

const api1 = fetch("https://api1.example.com/data").then((res) => res.json());
const api2 = fetch("https://api2.example.com/data").then((res) => res.json());

Promise.any([api1, api2])
  .then((data) => console.log("Dữ liệu nhận được:", data))
  .catch(() => console.log("Tất cả API đều thất bại"));

Giảm thời gian chờ đợi khi gọi nhiều API.
Hữu ích khi tải ảnh từ nhiều máy chủ CDN, chọn máy chủ phản hồi nhanh nhất.
Tăng hiệu suất khi làm việc với dữ liệu bất đồng bộ.

WeakRef và FinalizationRegistry – Quản lý bộ nhớ tốt hơn

Trước ES12:

Các object trong JavaScript được giữ lại trong bộ nhớ nếu có tham chiếu đến chúng, ngay cả khi không còn cần thiết, gây rò rỉ bộ nhớ.

Sau ES12 – Sử dụng WeakRef để tránh giữ object không cần thiết:

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 (GC)

Hữu ích trong lập trình game hoặc ứng dụng có nhiều object động.
Giúp tối ưu hóa bộ nhớ khi xử lý dữ liệu lớn.

Giúp làm việc với chuỗi dễ dàng hơn với replaceAll()

Trước đây, muốn thay thế tất cả chuỗi con trong JavaScript, lập trình viên phải dùng RegEx với cờ g (global).

Trước ES12:

let text = "Hello world, world!";
console.log(text.replace(/world/g, "JavaScript")); // "Hello JavaScript, JavaScript!"

Sau ES12 (Sử dụng replaceAll())

let text = "Hello world, world!";
console.log(text.replaceAll("world", "JavaScript")); // "Hello JavaScript, JavaScript!"

Tăng hiệu suất khi làm việc với chuỗi lớn.
Hữu ích khi xử lý văn bản, dữ liệu đầu vào từ người dùng.
Tránh nhầm lẫn khi sử dụng RegEx.

Tối ưu hóa khi truy cập object với Logical Operators in Optional Chaining

Trong ES12, ta có thể kết hợp Optional Chaining (?.) với các toán tử logic (&&, ||, ??) để tránh lỗi khi truy cập thuộc tính không tồn tại.

Trước ES12:

let user = {};
console.log(user && user.profile && user.profile.name); // undefined (cú pháp dài)

Sau ES12:

let user = {};
console.log(user?.profile?.name || "Không có thông tin"); // "Không có thông tin"

Giúp code an toàn hơn khi xử lý dữ liệu từ API hoặc database.
Tránh lỗi Cannot read properties of undefined.
Hữu ích khi làm việc với dữ liệu động như JSON.

Kết bài

ECMAScript 2021 (ES12) mang đến nhiều cải tiến quan trọng giúp lập trình JavaScript trở nên hiệu quả hơn, dễ đọc hơn và tối ưu hơn. Những tính năng như toán tử gán logic (&&=, ||=, ??=), Promise.any(), replaceAll(), WeakRef, và Optional Chaining kết hợp toán tử logic giúp lập trình viên viết code ngắn gọn, rõ ràng và an toàn hơn khi làm việc với dữ liệu động và xử lý bất đồng bộ.

Với những nâng cấp này, JavaScript tiếp tục khẳng định vị thế là một trong những ngôn ngữ lập trình mạnh mẽ và phổ biến nhất hiện nay. Việc nắm vững các tính năng của ES12 sẽ giúp lập trình viên tối ưu hiệu suất, quản lý bộ nhớ tốt hơn và giảm lỗi trong quá trình phát triển ứng dụng.

Nếu bạn là một lập trình viên JavaScript, hãy bắt đầu áp dụng ES12 ngay hôm nay để nâng cao chất lượng code và cải thiện hiệu suất ứng dụng của mình!

Bài viết liên quan