Một năm nữa lại đến với những nâng cấp tính năng JavaScript mới toanh trong ES15, hứa hẹn mang đến cho anh em lập trình viên những trải nghiệm coding phê pha hơn bao giờ hết.
Từ các tính năng bất đồng bộ xịn xò cho đến những cú pháp ngọt ngào với array, cùng với regex hiện đại, giờ đây viết code JavaScript dễ như ăn kẹo, nhanh như gió.
1. Tính năng group-by array native đã xuất hiện
Object.groupBy()
:
const people = [ { name: 'John', age: 25 }, { name: 'Jane', age: 30 }, { name: 'Jim', age: 25 }, { name: 'Jill', age: 30 }
]; const groupedByAge = Object.groupBy(people, person => person.age); console.log(groupedByAge);
/*
{ '25': [ { name: 'John', age: 25 }, { name: 'Jim', age: 25 } ], '30': [ { name: 'Jane', age: 30 }, { name: 'Jill', age: 30 } ]
}
*/
Cái này là thứ duy nhất giữ cho ông cố Lodash còn sống đấy các bạn ạ - giờ thì khỏi cần nữa rồi!
Mình cứ nghĩ là sẽ có một instance method mới như Array.prototype.groupBy
cơ, ai dè họ lại làm nó thành static vì lý do quái gì đó.
Rồi chúng ta còn có Map.groupBy
để group với object keys nữa chứ:
const map = new Map([ ['John', 25], ['Jane', 30], ['Jim', 25], ['Jill', 30]
]); const groupedByAge = Map.groupBy(map, ([name, age]) => age); console.log(groupedByAge);
/*
{ '25': [['John', 25], ['Jim', 25]], '30': [['Jane', 30], ['Jill', 30]]
}
*/
Nhưng mà hầu như chả ai group array theo kiểu này, nên chắc nó sẽ ít được dùng hơn nhiều.
2. Resolve promise từ bên ngoài mà không cần Deferred
Với Promise.withResolvers()
.
Trước đây muốn resolve promise từ bên ngoài thì phải dùng class Deferred:
class Deferred { constructor() { this.promise = new Promise((resolve, reject) => { this.resolve = resolve; this.reject = reject; }); }
} const deferred = new Deferred();
// ...
deferred.resolve(42);
Hoặc cài từ NPM - lại thêm một dependency nữa!
Nhưng giờ với Promise.withResolvers()
của ES15:
const [promise, resolve, reject] = Promise.withResolvers();
// ...
resolve(42);
Xem cách mình dùng nó để nhanh chóng biến event stream thành promise - await một observable:
async function waitForClick() { const [promise, resolve] = Promise.withResolvers(); document.addEventListener('click', resolve, { once: true }); return promise;
} const clickEvent = await waitForClick();
console.log('Clicked!', clickEvent);
3. Nâng cấp hiệu năng Buffer
Buffer là những kho dữ liệu nhỏ để lưu trữ dữ liệu tạm thời mà ứng dụng của bạn tạo ra.
Chúng giúp việc truyền và xử lý dữ liệu qua các giai đoạn khác nhau trong pipeline trở nên cực kỳ dễ dàng.
Các pipeline như:
- Xử lý file: File đầu vào → buffer → xử lý → buffer mới → file đầu ra
- Stream video: Response từ network → buffer → hiển thị khung hình video...
Với buffer, mỗi giai đoạn xử lý dữ liệu với tốc độ khác nhau, độc lập với nhau.
Nhưng chuyện gì xảy ra khi lượng dữ liệu chạy qua pipeline vượt quá dung lượng buffer?
Trước đây chúng ta phải copy toàn bộ dữ liệu hiện tại trong buffer sang một buffer lớn hơn.
Điều này rất tệ cho hiệu năng, đặc biệt khi có RẤT NHIỀU dữ liệu trong pipeline.
ES15 mang đến cho chúng ta giải pháp cho vấn đề này: Resizable array buffer.
const buffer = new ArrayBuffer(1024); // Tạo buffer 1KB
// ...
buffer.resize(2048); // Tăng kích thước buffer lên 2KB mà không cần copy dữ liệu
4. Nâng cấp bất đồng bộ
Atomics.waitAsync()
: Một tính năng lập trình bất đồng bộ mạnh mẽ khác trong ES2024:
Đó là khi 2 agent chia sẻ một buffer...
Và agent 1 "ngủ" và đợi agent 2 hoàn thành một tác vụ.
Khi agent 2 xong việc, nó thông báo bằng cách sử dụng buffer dùng chung như một kênh truyền.
const sharedBuffer = new SharedArrayBuffer(1024);
const sharedArray = new Int32Array(sharedBuffer); // Agent 1
async function waitForSignal() { await Atomics.waitAsync(sharedArray, 0, 0); console.log('Signal received!');
} waitForSignal(); // Agent 2
function sendSignal() { Atomics.store(sharedArray, 0, 1); Atomics.notify(sharedArray, 0, 1);
} setTimeout(sendSignal, 1000);
Bạn sẽ hoàn toàn đúng nếu nghĩ rằng điều này tương tự như async/await bình thường.
Nhưng sự khác biệt lớn nhất là: 2 agent có thể tồn tại trong các ngữ cảnh code hoàn toàn khác nhau - chúng chỉ cần truy cập vào cùng một buffer.
Và: nhiều agent có thể truy cập hoặc chờ đợi trên buffer dùng chung tại các thời điểm khác nhau - và bất kỳ agent nào cũng có thể thông báo để "đánh thức" tất cả các agent khác.
Nó giống như một mạng P2P; async/await giống như request-response kiểu client-server.
5. Cờ v trong Regex & các phép toán tập hợp
Một tính năng hoàn toàn mới giúp regex trở nên gọn gàng và trực quan hơn nhiều.
Tìm kiếm và thao tác các chuỗi phức tạp bằng các mẫu biểu thức - với sự trợ giúp của các phép toán tập hợp:
const pattern = /[a-z&&[^aeiou]]/v;
console.log(pattern.test('b')); // true
console.log(pattern.test('a')); // false
Để khớp với các tập ký tự Unicode ngày càng tăng, như:
- Emoji: 😀, ❤️, 👍, 🎉, v.v.
- Chữ cái có dấu: é, à, ö, ñ, v.v.
- Ký hiệu và ký tự không phải Latin: ©, ®, €, £, µ, ¥, v.v.
Vì vậy ở đây chúng ta sử dụng regex Unicode và cờ v để khớp với tất cả các chữ cái Hy Lạp:
const greekLetters = /\p{Script=Greek}/v;
console.log(greekLetters.test('α')); // true
console.log(greekLetters.test('a')); // false
Cuối cùng
Nhìn chung, ES15 là một bước nhảy vọt đáng kể cho JavaScript với một số tính năng thiết yếu cho phát triển hiện nay. Đặc biệt là buffer và bất đồng bộ, giúp bạn xử lý dữ liệu nhanh hơn và hiệu quả hơn bao giờ hết, bạn nào mà làm việc với file hay stream thì chắc chắn sẽ thích thú với những cải tiến này.
Những cải tiến này giúp bạn viết code sạch hơn, súc tích hơn và rõ ràng hơn.
Ok, chuẩn bị tinh thần đón chào kỷ nguyên mới của JavaScript thôi. Hy vọng với bài viết này, anh em đã nắm được phần nào những tính năng đỉnh cao sắp tới trong phiên bản ES15 2024.
Hãy tận dụng triệt để sức mạnh của chúng để nâng tầm code của mình lên một đẳng cấp mới nhé. Đảm bảo đời code của các bạn sẽ phê pha hơn bao giờ hết!
Thôi chốt lại là: Ngon, bổ, rẻ, xịn, mịn - ES15 có tất! Các bạn đừng quên like, share và subscribe nhé. Hẹn gặp lại anh em trong những bài viết hay ho tiếp theo. Lập trình vui vẻ nhé mọi người!