Những tính năng mới trong ECMAScript 2024 (ES15) 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, và sự phát triển của nó luôn được thúc đẩy bởi các bản cập nhật từ ECMAScript (ES). Mỗi năm, ECMAScript lại mang đến những tính năng mới giúp cải thiện hiệu suất, tối ưu hóa cú pháp và nâng cao khả năng lập trình. Năm 2024, phiên bản ECMAScript 2024 (ES15) tiếp tục giới thiệu nhiều cải tiến quan trọng, từ việc mở rộng các phương thức thao tác dữ liệu đến cải tiến về lập trình bất đồng bộ. Những thay đổi này không chỉ giúp lập trình viên viết mã hiệu quả hơn mà còn mở ra nhiều khả năng mới trong việc xây dựng ứng dụng web và hệ thống lớn. Hãy cùng tìm hiểu những tính năng đáng chú ý trong ES15 và cách chúng có thể nâng tầm trải nghiệm lập trình JavaScript.

Giới thiệu về ECMAScript 2024 (ES15) trong JavaScript

ECMAScript (ES) là tiêu chuẩn chính thức của JavaScript, được phát triển và duy trì bởi tổ chức ECMA International. Hàng năm, một phiên bản mới của ECMAScript được phát hành, mang lại các tính năng và cải tiến nhằm nâng cao hiệu suất, tối ưu cú pháp và cải thiện trải nghiệm lập trình.

ECMAScript 2024 (ES15) là phiên bản mới nhất, tiếp tục xu hướng cải tiến từ những năm trước, tập trung vào việc mở rộng khả năng thao tác với dữ liệu, tối ưu hóa lập trình bất đồng bộ, và cải thiện hiệu suất tổng thể của JavaScript. Một số tính năng quan trọng trong ES15 bao gồm:

  • Nhóm dữ liệu dễ dàng hơn với Object.groupBy()Map.groupBy().

  • Cải tiến quản lý Promise với Promise.withResolvers().

  • Hỗ trợ bộ nhớ linh hoạt hơn với Resizable ArrayBuffer.

  • Nâng cấp lập trình đồng bộ với Atomics.waitAsync().

  • Mở rộng cú pháp Regular Expression với cờ v, giúp viết biểu thức chính quy mạnh mẽ hơn.

Tầm quan trọng của ECMAScript 2024 (ES15) trong phát triển JavaScript

Sự phát triển của ECMAScript đóng vai trò quan trọng trong việc định hình hướng đi của JavaScript, giúp ngôn ngữ này ngày càng mạnh mẽ và phù hợp hơn với nhu cầu của lập trình viên. Với ES15, JavaScript tiếp tục được cải thiện ở các khía cạnh quan trọng:

Tối ưu hóa hiệu suất và quản lý bộ nhớ

  • Resizable ArrayBuffer giúp quản lý dữ liệu hiệu quả hơn, đặc biệt trong các ứng dụng xử lý dữ liệu lớn hoặc đồ họa.

  • Atomics.waitAsync() giúp cải thiện hiệu suất lập trình đồng bộ, hữu ích cho các ứng dụng đa luồng như Web Workers.

Cải thiện trải nghiệm lập trình và cú pháp dễ đọc hơn

  • Object.groupBy()Map.groupBy() giúp thao tác với mảng dữ liệu dễ dàng hơn, giảm bớt sự phụ thuộc vào các thư viện bên ngoài.

  • Promise.withResolvers() cung cấp một cách tiếp cận rõ ràng và linh hoạt hơn để xử lý bất đồng bộ, giúp mã nguồn trở nên dễ hiểu và bảo trì hơn.

Nâng cao khả năng thao tác với chuỗi và biểu thức chính quy

  • Cờ v trong Regular Expression giúp viết các biểu thức phức tạp theo cách dễ hiểu hơn, đặc biệt hữu ích cho xử lý văn bản, tìm kiếm dữ liệu và thao tác chuỗi.

Tạo tiền đề cho các tính năng mới trong tương lai

  • Những đề xuất như Pipeline Operator (|>)Records & Tuples đang được cân nhắc, hứa hẹn mang lại những cải tiến lớn hơn cho JavaScript trong các phiên bản tiếp theo.

Nhìn chung, ECMAScript 2024 (ES15) không chỉ giúp tối ưu hiệu suất và khả năng lập trình mà còn góp phần làm cho JavaScript trở thành một ngôn ngữ mạnh mẽ, linh hoạt hơn, đáp ứng nhu cầu của các dự án từ nhỏ đến lớn. Với những cập nhật này, lập trình viên JavaScript có thể viết mã hiệu quả hơn, dễ đọc hơn và tận dụng tốt hơn các công nghệ hiện đại.

Các tính năng mới trong ECMAScript 2024 (ES15) trong JavaScript

ECMAScript 2024 (ES15) mang đến nhiều tính năng mới giúp lập trình viên thao tác dữ liệu dễ dàng hơn, tối ưu hóa hiệu suất xử lý bất đồng bộ và cải thiện khả năng làm việc với bộ nhớ. Dưới đây là những cải tiến quan trọng trong phiên bản này.

Object.groupBy() và Map.groupBy()

Object.groupBy()

Phương thức Object.groupBy() giúp nhóm các phần tử trong một mảng dựa trên một tiêu chí nhất định, trả về một đối tượng (Object) có các khóa là tiêu chí nhóm và giá trị là mảng các phần tử thuộc nhóm đó.

Cú pháp

Object.groupBy(array, callback);
  • array: Mảng cần nhóm.

  • callback: Hàm nhận từng phần tử của mảng và trả về một giá trị làm tiêu chí nhóm.

Ví dụ

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

const grouped = Object.groupBy(numbers, (num) => (num % 2 === 0 ? 'even' : 'odd'));

console.log(grouped);
// Output:
// {
//   odd: [1, 3, 5, 7, 9],
//   even: [2, 4, 6, 8, 10]
// }

Ở đây, các số trong mảng được nhóm thành hai nhóm: số chẵn (even) và số lẻ (odd).

Map.groupBy()

Tương tự Object.groupBy(), phương thức Map.groupBy() cũng nhóm các phần tử của một mảng theo một tiêu chí nhất định, nhưng thay vì trả về một đối tượng (Object), nó trả về một Map.

Cú pháp

Map.groupBy(array, callback);
  • array: Mảng cần nhóm.

  • callback: Hàm nhận từng phần tử của mảng và trả về một giá trị làm tiêu chí nhóm.

Ví dụ

const words = ['apple', 'banana', 'cherry', 'apricot', 'blueberry'];

const groupedWords = Map.groupBy(words, (word) => word.charAt(0));

console.log(groupedWords);
// Output:
// Map {
//   'a' => ['apple', 'apricot'],
//   'b' => ['banana', 'blueberry'],
//   'c' => ['cherry']
// }

Ở đây, các từ được nhóm theo ký tự đầu tiên của chúng (a, b, c).

Điểm khác biệt chính:

  • Object.groupBy() trả về một object, có thể gặp vấn đề khi khóa là số hoặc có trùng lặp.

  • const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
    console.log(buffer.byteLength); // Output: 8
    
    buffer.resize(12);
    console.log(buffer.byteLength); // Output: 12

Promise.withResolvers()

Phương thức Promise.withResolvers() giúp dễ dàng tạo một Promise cùng với các hàm resolvereject, giúp quản lý bất đồng bộ hiệu quả hơn.

const { promise, resolve, reject } = Promise.withResolvers();

Ví dụ

const { promise, resolve, reject } = Promise.withResolvers();

setTimeout(() => {
  resolve("Data loaded successfully");
}, 2000);

promise.then(console.log);
// Output (sau 2 giây): "Data loaded successfully"

Với cách này, chúng ta có thể linh hoạt kiểm soát thời điểm Promise hoàn thành mà không cần phải gán biến tạm như cách truyền thống.

Resizable ArrayBuffer

Trước đây, ArrayBuffer có kích thước cố định khi được tạo ra, gây khó khăn nếu cần thay đổi dung lượng bộ nhớ mà không làm mất dữ liệu. ES15 giới thiệu Resizable ArrayBuffer, cho phép thay đổi kích thước ArrayBuffer sau khi khởi tạo mà không cần sao chép dữ liệu.

Cú pháp

const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
buffer.resize(12);
  • maxByteLength: Giới hạn tối đa mà ArrayBuffer có thể mở rộng.

  • resize(newSize): Thay đổi kích thước ArrayBuffer.

Ví dụ

const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
console.log(buffer.byteLength); // Output: 8

buffer.resize(12);
console.log(buffer.byteLength); // Output: 12

Điều này giúp quản lý bộ nhớ hiệu quả hơn, đặc biệt trong các ứng dụng xử lý dữ liệu lớn như đồ họa, WebAssembly hoặc machine learning.

Atomics.waitAsync()

Trong lập trình đa luồng với Web Workers, phương thức Atomics.wait() cho phép một luồng (thread) chờ tín hiệu từ luồng khác, nhưng chỉ hoạt động trong Worker Threads đồng bộ.

ES15 giới thiệu Atomics.waitAsync(), cho phép một luồng "ngủ" và đợi một luồng khác hoàn thành, giúp xử lý bất đồng bộ hiệu quả hơn.

Ví dụ

const sharedBuffer = new SharedArrayBuffer(4);
const int32 = new Int32Array(sharedBuffer);

Atomics.waitAsync(int32, 0, 0).value.then(() => {
  console.log("Woken up!");
});

// Một luồng khác sẽ đánh thức luồng đang ngủ:
setTimeout(() => {
  Atomics.notify(int32, 0, 1);
}, 2000);

Sau 2 giây, Atomics.notify() đánh thức luồng đang đợi, in ra "Woken up!".

Cờ 'v' trong Regular Expression

ES15 giới thiệu cờ v mới cho Regular Expressions, giúp biểu thức chính quy mạnh mẽ hơn với toán tử logic trên character class.

Toán tử hỗ trợ

  • && (AND) → Chỉ chấp nhận ký tự xuất hiện trong cả hai tập hợp.

  • -- (Difference) → Loại bỏ các ký tự của tập hợp thứ hai khỏi tập hợp thứ nhất.

Ví dụ

const regex = /[\p{Letter}&&\p{Uppercase}]/v;
console.log(regex.test("A")); // true
console.log(regex.test("a")); // false
console.log(regex.test("1")); // false

Ở đây, biểu thức chỉ khớp với chữ cái in hoa, kết hợp giữa \p{Letter} (tất cả chữ cái) và \p{Uppercase} (chữ in hoa).

Các tính năng đang được đề xuất hoặc thử nghiệm trong ECMAScript

Bên cạnh các tính năng chính thức trong ECMAScript 2024 (ES15), một số đề xuất mới đang được xem xét hoặc thử nghiệm. Những tính năng này hứa hẹn sẽ tiếp tục cải thiện JavaScript, giúp mã nguồn dễ đọc hơn, tăng hiệu suất và tối ưu hóa việc quản lý dữ liệu.

Pipeline Operator (|>)

Toán tử Pipeline (|>) giúp đơn giản hóa việc chuỗi hóa (chaining) các thao tác, làm cho mã nguồn dễ đọc và bảo trì hơn. Tương tự như cách Unix pipes (|) hoạt động, toán tử Pipeline giúp truyền kết quả của một hàm vào hàm tiếp theo một cách trực quan hơn.

Thông thường, để xử lý dữ liệu qua nhiều bước, lập trình viên sử dụng cách lồng hàm hoặc method chaining:

const result = formatData(parseData(fetchData(url)));

Hoặc sử dụng chaining (khi có sẵn các phương thức .map(), .filter(), ...)

const result = data
  .map(parseData)
  .filter(isValid)
  .map(formatData);

Mặc dù chaining giúp đọc mã dễ hơn, nhưng nó chỉ áp dụng được khi dữ liệu là một mảng hoặc đối tượng có phương thức tương ứng.

Pipeline Operator (|>) giải quyết vấn đề như thế nào?

Pipeline Operator cho phép truyền giá trị một cách tự nhiên hơn mà không cần lồng hàm:

const result = fetchData(url)
  |> parseData
  |> formatData;

Ví dụ cụ thể

const double = (x) => x * 2;
const square = (x) => x * x;

const result = 5 |> double |> square;
console.log(result); // Output: 100

Ở đây, 5 được truyền qua double() rồi tiếp tục truyền kết quả vào square(), giúp mã ngắn gọn và dễ đọc hơn.

Records và Tuples – Cấu trúc dữ liệu bất biến

Hiện tại, JavaScript sử dụng ObjectsArrays để lưu trữ dữ liệu. Tuy nhiên, những cấu trúc này có thể thay đổi sau khi được tạo, dẫn đến rủi ro sửa đổi ngoài ý muốn.

ECMAScript đề xuất Records (#{} ) và Tuples (#[]), là hai kiểu dữ liệu bất biến (immutable), giúp đảm bảo dữ liệu không thể bị thay đổi sau khi được tạo.

Records (#{}) – Tương tự Object nhưng bất biến

Một Record giống như một Object, nhưng không thể thay đổi giá trị sau khi được khởi tạo.

Ví dụ

const user = #{ name: "Alice", age: 30 };

console.log(user.name); // "Alice"

//  Không thể thay đổi giá trị
user.age = 31; // TypeError: Cannot assign to read only property

Ở đây, user hoạt động như một Object nhưng là bất biến, giúp tránh lỗi vô tình thay đổi dữ liệu.

So sánh với Object

Đặc điểm Object Record (#{})
Có thể thay đổi không? Có thể sửa đổi Không thể sửa đổi
Hỗ trợ so sánh sâu? Không Có (giúp so sánh dễ dàng hơn)
Được dùng trong Set/Map? Có (vì hỗ trợ so sánh sâu)

So sánh sâu (Deep Equality) giúp kiểm tra hai object có giống nhau không mà không cần so sánh từng thuộc tính

const obj1 = { name: "Alice" };
const obj2 = { name: "Alice" };
console.log(obj1 === obj2); // false (vì là hai object khác nhau)

const rec1 = #{ name: "Alice" };
const rec2 = #{ name: "Alice" };
console.log(rec1 === rec2); // true (vì cùng nội dung)

Điều này giúp giảm lỗi khi so sánh object trong JavaScript.

Tuples (#[]) – Tương tự Array nhưng bất biến

Một Tuple hoạt động giống như một Array, nhưng giá trị bên trong không thể bị thay đổi.

Ví dụ

const colors = #["red", "green", "blue"];

console.log(colors[0]); // "red"

//  Không thể thay đổi giá trị
colors[1] = "yellow"; // TypeError: Cannot assign to read only property

So sánh với Array

Đặc điểm Array Tuple (#[])
Có thể thay đổi không? Có thể sửa đổi Không thể sửa đổi
Hỗ trợ so sánh sâu? Không
Dùng để lưu trạng thái? Không an toàn An toàn hơn

Với Tuples, dữ liệu trạng thái không thể bị thay đổi ngoài ý muốn, giúp lập trình hiệu quả và an toàn hơn.

Kết bài

ECMAScript 2024 (ES15) tiếp tục mang đến những cải tiến quan trọng cho JavaScript, giúp ngôn ngữ này trở nên mạnh mẽ, tối ưu và dễ sử dụng hơn. Các tính năng mới như Object.groupBy(), Promise.withResolvers(), Resizable ArrayBuffer, hay Atomics.waitAsync() giúp lập trình viên làm việc với dữ liệu và xử lý bất đồng bộ hiệu quả hơn.

Bên cạnh đó, các đề xuất như Pipeline Operator (|>) giúp đơn giản hóa chuỗi thao tác, trong khi Records & Tuples (#{}#[]) mang lại khả năng quản lý dữ liệu bất biến, tăng cường tính an toàn và hiệu suất cho ứng dụng.

Những cải tiến này không chỉ giúp code gọn gàng hơn, dễ bảo trì hơn, mà còn mở ra nhiều khả năng mới cho các ứng dụng web hiện đại. JavaScript tiếp tục phát triển để đáp ứng nhu cầu ngày càng cao của cộng đồng lập trình viên, giữ vững vị thế là một trong những ngôn ngữ lập trình phổ biến nhất thế giới.

Bài viết liên quan