Kết quả phù hợp hơn với String.prototype.matchAll()

Joe Medley
Joe Medley

Chrome 73 giới thiệu phương thức String.prototype.matchAll(). Hàm này hoạt động tương tự như match(), nhưng trả về một trình lặp với tất cả các biểu thức chính quy khớp trong một biểu thức chính quy toàn cục hoặc cố định. Đây là một cách đơn giản để lặp lại các kết quả trùng khớp, đặc biệt là khi bạn cần quyền truy cập để thu thập các nhóm.

Có vấn đề gì với hàm match()?

Câu trả lời ngắn gọn là không có gì, trừ khi bạn đang cố gắng trả về các kết quả trùng khớp trên toàn cục bằng các nhóm chụp ảnh. Sau đây là một câu đố về lập trình dành cho bạn. Hãy xem xét mã sau:

const regex = /t(e)(st(\d?))/g;
const string = 'test1test2';
const results = string.match(regex);
console.log(results);
// → ['test1', 'test2']

Hãy chạy lệnh này trong bảng điều khiển và nhận thấy thao tác này trả về một mảng chứa các chuỗi 'test1''test2'. Nếu tôi xoá cờ g khỏi biểu thức chính quy thì kết quả tôi nhận được sẽ có tất cả các nhóm thu thập, nhưng tôi chỉ nhận được kết quả khớp đầu tiên. Thông báo sẽ có dạng như sau:

['test1', 'e', 'st1', '2', index: 0, input: 'test1test2', groups: undefined]

Chuỗi này chứa kết quả phù hợp thứ hai có thể bắt đầu bằng 'test2' nhưng tôi không có kết quả đó. Sau đây là câu đố: làm cách nào để tôi thu thập tất cả các nhóm thu thập cho từng kết quả trùng khớp? Công cụ giải thích cho đề xuất String.prototype.matchAll() cho thấy hai phương pháp khả thi. Tôi sẽ không mô tả chúng vì hy vọng bạn sẽ không cần đến chúng nữa.

String.prototype.matchAll()

Các ví dụ giải thích sẽ hiển thị như thế nào với matchAll()? Hãy xem qua.

const regex = /t(e)(st(\d?))/g;
const string = 'test1test2';
const matches = string.matchAll(regex);
for (const match of matches) {
  console.log(match);
}

Bạn cần lưu ý một vài điều về việc này. Không giống như match() trả về một mảng trong kết quả tìm kiếm toàn cầu, matchAll() trả về một biến lặp hoạt động ổn định với vòng lặp for...of. Trình lặp này tạo một mảng cho mỗi kết quả trùng khớp, bao gồm cả các nhóm thu thập cùng với một vài dữ liệu bổ sung. Nếu bạn in các tệp này ra bảng điều khiển, chúng sẽ trông giống như sau:

['test1', 'e', 'st1', '1', index: 0, input: 'test1test2', groups: undefined]
['test2', 'e', 'st2', '2', index: 5, input: 'test1test2', groups: undefined]

Bạn có thể nhận thấy rằng giá trị cho mỗi kết quả trùng khớp là một mảng có cùng định dạng như được match() trả về cho biểu thức chính quy không phải toàn hệ thống.

Tài liệu bổ sung

Điều này chủ yếu dành cho những người mới làm quen với biểu thức chính quy hoặc những người không phải là chuyên gia về nó. Bạn có thể nhận thấy kết quả của cả match() và matchAll() (đối với mỗi lần lặp) là các mảng có một số thuộc tính được đặt tên bổ sung. Khi chuẩn bị bài viết này, tôi nhận thấy rằng các thuộc tính này có một số điểm thiếu tài liệu về MDN (tôi đã khắc phục). Dưới đây là phần mô tả nhanh.

index
Chỉ mục của kết quả đầu tiên trong chuỗi gốc. Trong ví dụ trên, test2 bắt đầu từ vị trí 5 do đó index có giá trị là 5.
input
Chuỗi hoàn chỉnh dùng để chạy matchAll(). Trong ví dụ của tôi, đó là 'test1test2'.
groups
Chứa kết quả của bất kỳ nhóm thu thập có tên nào được chỉ định trong biểu thức chính quy của bạn.

Kết luận

Nếu tôi bỏ lỡ bất kỳ điều gì, vui lòng cho tôi biết trong phần nhận xét bên dưới. Bạn có thể đọc thêm về các thay đổi gần đây đối với JavaScript trong các bản cập nhật trước đây hoặc trên trang web V8.