Non-capturing group: (?:...)

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.

Một non-capturing group nhóm một subpattern, cho phép bạn áp dụng một quantifier cho toàn bộ nhóm hoặc sử dụng disjunctions bên trong nó. Nó hoạt động như toán tử nhóm trong các biểu thức JavaScript, và không giống như capturing groups, nó không ghi nhớ văn bản đã khớp, cho phép hiệu suất tốt hơn và tránh nhầm lẫn khi pattern cũng chứa các capturing groups hữu ích.

Cú pháp

regex
(?:pattern)

Tham số

pattern

Một pattern bao gồm bất cứ thứ gì bạn có thể sử dụng trong một regex literal, bao gồm cả disjunction.

Ví dụ

Nhóm một subpattern và áp dụng quantifier

Trong ví dụ sau, chúng ta kiểm tra xem một đường dẫn file có kết thúc bằng styles.css hoặc styles.[a hex hash].css không. Vì toàn bộ phần \.[\da-f]+ là tùy chọn, để áp dụng quantifier ? cho nó, chúng ta cần nhóm nó thành một atom mới. Sử dụng non-capturing group cải thiện hiệu suất bằng cách không tạo ra thông tin khớp thêm mà chúng ta không cần.

js
function isStylesheet(path) {
  return /styles(?:\.[\da-f]+)?\.css$/.test(path);
}

isStylesheet("styles.css"); // true
isStylesheet("styles.1234.css"); // true
isStylesheet("styles.cafe.css"); // true
isStylesheet("styles.1234.min.css"); // false

Nhóm một disjunction

Một disjunction có độ ưu tiên thấp nhất trong một regular expression. Nếu bạn muốn sử dụng một disjunction như một phần của pattern lớn hơn, bạn phải nhóm nó. Bạn được khuyến khích sử dụng non-capturing group trừ khi bạn dựa vào văn bản đã khớp của disjunction. Ví dụ sau khớp các phần mở rộng file, sử dụng cùng mã như bài viết input boundary assertion:

js
function isImage(filename) {
  return /\.(?:png|jpe?g|webp|avif|gif)$/i.test(filename);
}

isImage("image.png"); // true
isImage("image.jpg"); // true
isImage("image.pdf"); // false

Tránh nguy cơ khi tái cấu trúc

Các capturing groups được truy cập theo vị trí của chúng trong pattern. Nếu bạn thêm hoặc xóa một capturing group, bạn cũng phải cập nhật vị trí của các capturing groups khác, nếu bạn đang truy cập chúng qua kết quả khớp hoặc backreferences. Đây có thể là nguồn gốc của các lỗi, đặc biệt nếu hầu hết các nhóm chỉ vì mục đích cú pháp (để áp dụng quantifiers hoặc nhóm disjunctions). Sử dụng non-capturing groups tránh vấn đề này, và cho phép các chỉ số của các capturing groups thực sự dễ dàng theo dõi.

Ví dụ, giả sử chúng ta có một hàm khớp pattern title='xxx' trong một chuỗi (ví dụ lấy từ capturing group). Để đảm bảo các dấu ngoặc kép khớp nhau, chúng ta sử dụng backreference để tham chiếu đến dấu ngoặc kép đầu tiên.

js
function parseTitle(metastring) {
  return metastring.match(/title=(["'])(.*?)\1/)[2];
}

parseTitle('title="foo"'); // 'foo'

Nếu sau này chúng ta quyết định thêm name='xxx' làm bí danh cho title=, chúng ta sẽ cần nhóm disjunction trong một nhóm khác:

js
function parseTitle(metastring) {
  // Oops — the backreference and index access are now off by one!
  return metastring.match(/(title|name)=(["'])(.*?)\1/)[2];
}

parseTitle('name="foo"'); // Cannot read properties of null (reading '2')
// Because \1 now refers to the "name" string, which isn't found at the end.

Thay vì tìm tất cả các nơi chúng ta đang tham chiếu đến các chỉ số của capturing groups và cập nhật chúng từng cái một, tốt hơn là tránh sử dụng capturing group:

js
function parseTitle(metastring) {
  // Do not capture the title|name disjunction
  // because we don't use its value
  return metastring.match(/(?:title|name)=(["'])(.*?)\1/)[2];
}

parseTitle('name="foo"'); // 'foo'

Named capturing groups là một cách khác để tránh nguy cơ khi tái cấu trúc. Nó cho phép các capturing groups được truy cập bằng tên tùy chỉnh, không bị ảnh hưởng khi các capturing groups khác được thêm hoặc xóa.

Thông số kỹ thuật

Specification
ECMAScript® 2027 Language Specification
# prod-Atom

Tương thích trình duyệt

Xem thêm