Iterator
Baseline
Widely available
*
This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2016.
* Some parts of this feature may have varying levels of support.
Đối tượng Iterator là đối tượng tuân theo giao thức iterator bằng cách cung cấp phương thức next() trả về đối tượng kết quả iterator. Tất cả các iterator tích hợp sẵn đều kế thừa từ lớp Iterator. Lớp Iterator cung cấp phương thức [Symbol.iterator]() trả về chính đối tượng iterator, làm cho iterator cũng có thể lặp. Nó cũng cung cấp một số phương thức trợ giúp để làm việc với các iterator.
Mô tả
Sau đây là tất cả các iterator JavaScript tích hợp sẵn:
- Array Iterator được trả về bởi
Array.prototype.values(),Array.prototype.keys(),Array.prototype.entries(),Array.prototype[Symbol.iterator](),TypedArray.prototype.values(),TypedArray.prototype.keys(),TypedArray.prototype.entries(),TypedArray.prototype[Symbol.iterator](), vàarguments[Symbol.iterator](). - String Iterator được trả về bởi
String.prototype[Symbol.iterator](). - Map Iterator được trả về bởi
Map.prototype.values(),Map.prototype.keys(),Map.prototype.entries(), vàMap.prototype[Symbol.iterator](). - Set Iterator được trả về bởi
Set.prototype.values(),Set.prototype.keys(),Set.prototype.entries(), vàSet.prototype[Symbol.iterator](). - RegExp String Iterator được trả về bởi
RegExp.prototype[Symbol.matchAll]()vàString.prototype.matchAll(). - Đối tượng
Generatorđược trả về bởi hàm generator. - Segments Iterator được trả về bởi phương thức
[Symbol.iterator]()của đối tượngSegmentsđược trả về bởiIntl.Segmenter.prototype.segment(). - Iterator Helper được trả về bởi các phương thức trợ giúp iterator như
Iterator.prototype.filter()vàIterator.prototype.map().
Các Web API cũng có thể trả về iterator. Một số tái sử dụng các iterator JavaScript cốt lõi trong khi một số khác định nghĩa các iterator riêng của chúng. Ví dụ:
- Các đối tượng Array-Like như
NodeListtrả về Array Iterator từ các phương thức tương ứngkeys(),values(),entries(), và[Symbol.iterator](). - Các đối tượng Map-Like từ Web API như
Headerstrả về kiểu iterator riêng như Headers Iterator từ các phương thức tương ứngkeys(),values(),entries(), và[Symbol.iterator](). - Các đối tượng Set-Like từ Web API như
FontFaceSettrả về kiểu iterator riêng như FontFaceSet Iterator từ các phương thức tương ứngkeys(),values(),entries(), và[Symbol.iterator]().
Note:
NodeIterator và các giao diện cũ khác được đặt tên như vậy nhưng không tuân theo giao thức iterator hay giao thức iterable.
Mỗi iterator này có một đối tượng prototype riêng, định nghĩa phương thức next() được sử dụng bởi iterator cụ thể đó. Ví dụ, tất cả các đối tượng string iterator kế thừa từ đối tượng ẩn StringIteratorPrototype, có phương thức next() lặp chuỗi này theo điểm mã. StringIteratorPrototype cũng có thuộc tính [Symbol.toStringTag] có giá trị khởi tạo là chuỗi "String Iterator". Thuộc tính này được dùng trong Object.prototype.toString(). Tương tự, các prototype iterator khác cũng có giá trị [Symbol.toStringTag] riêng của chúng, giống với tên được đặt ở trên.
Tất cả các đối tượng prototype này kế thừa từ Iterator.prototype, cung cấp phương thức [Symbol.iterator]() trả về chính đối tượng iterator, làm cho iterator cũng có thể lặp.
Phương thức trợ giúp iterator
Note:
Các phương thức này là các trợ giúp iterator, không phải trợ giúp iterable, vì yêu cầu duy nhất để một đối tượng có thể lặp là sự hiện diện của phương thức [Symbol.iterator](). Không có prototype dùng chung để cài đặt các phương thức này.
Lớp Iterator cung cấp một số phương thức trợ giúp để làm việc với các iterator. Ví dụ, bạn có thể bị cám dỗ làm như sau:
const nameToDeposit = new Map([
["Anne", 1000],
["Bert", 1500],
["Carl", 2000],
]);
const totalDeposit = [...nameToDeposit.values()].reduce((a, b) => a + b);
Điều này trước tiên chuyển đổi iterator được trả về bởi Map.prototype.values() thành mảng, sau đó sử dụng phương thức Array.prototype.reduce() để tính tổng. Tuy nhiên, điều này vừa tạo ra mảng trung gian vừa lặp mảng hai lần. Thay vào đó, bạn có thể sử dụng phương thức reduce() của chính iterator:
const totalDeposit = nameToDeposit.values().reduce((a, b) => a + b);
Phương thức này có thể hiệu quả hơn, đặc biệt về mặt bộ nhớ, vì nó chỉ lặp iterator một lần mà không ghi nhớ bất kỳ giá trị trung gian nào. Các phương thức trợ giúp iterator cần thiết để làm việc với các iterator vô hạn:
function* fibonacci() {
let current = 1;
let next = 1;
while (true) {
yield current;
[current, next] = [next, current + next];
}
}
const seq = fibonacci();
const firstThreeDigitTerm = seq.find((n) => n >= 100);
Bạn không thể chuyển đổi seq thành mảng, vì nó là vô hạn. Thay vào đó, bạn có thể sử dụng phương thức find() của chính iterator, chỉ lặp seq đến mức cần thiết để tìm giá trị đầu tiên thỏa mãn điều kiện.
Bạn sẽ tìm thấy nhiều phương thức iterator tương tự với các phương thức mảng, chẳng hạn như:
Iterator.prototype.drop() và Iterator.prototype.take() kết hợp phần nào tương tự với Array.prototype.slice().
Các đối tượng trợ giúp iterator
Note: Đối tượng trợ giúp iterator và phương thức trợ giúp iterator là hai khái niệm khác nhau. Đối tượng trợ giúp iterator có thể được phát hiện tại thời gian chạy, trong khi "phương thức trợ giúp iterator" chỉ là tên cho một tập hợp các phương thức hiểu. Iterator helper có thể đề cập đến đối tượng hoặc phương thức, tùy thuộc vào ngữ cảnh.
Trong số các phương thức trợ giúp iterator, filter(), flatMap(), map(), drop(), và take() trả về đối tượng Iterator Helper mới. Iterator helper cũng là instance Iterator, làm cho các phương thức trợ giúp này có thể được xâu chuỗi. Tất cả các đối tượng iterator helper kế thừa từ đối tượng prototype chung, triển khai giao thức iterator:
next()-
Gọi phương thức
next()của iterator cơ bản, áp dụng phương thức trợ giúp cho kết quả và trả về kết quả. return()-
Gọi phương thức
return()của iterator cơ bản và trả về kết quả.
Iterator helper chia sẻ cùng nguồn dữ liệu với iterator cơ bản, vì vậy việc lặp iterator helper khiến iterator cơ bản cũng được lặp. Không có cách nào để "phân nhánh" một iterator để cho phép nó được lặp nhiều lần.
const it = [1, 2, 3].values();
const it2 = it.drop(0); // Essentially a copy
console.log(it.next().value); // 1
console.log(it2.next().value); // 2
console.log(it.next().value); // 3
Các iterator đúng nghĩa
Có hai loại "iterator": các đối tượng tuân theo giao thức iterator (yêu cầu tối thiểu là sự hiện diện của phương thức next()), và các đối tượng kế thừa từ lớp Iterator, được hưởng các phương thức trợ giúp. Chúng không kéo theo nhau — các đối tượng kế thừa từ Iterator không tự động trở thành iterator, vì lớp Iterator không định nghĩa phương thức next(). Thay vào đó, đối tượng cần định nghĩa phương thức next() của chính nó. Iterator đúng nghĩa là đối tượng vừa tuân theo giao thức iterator vừa kế thừa từ Iterator, và hầu hết code đều mong muốn các iterator là iterator đúng nghĩa và các iterable trả về iterator đúng nghĩa. Để tạo iterator đúng nghĩa, định nghĩa lớp mở rộng Iterator, hoặc sử dụng phương thức Iterator.from().
class MyIterator extends Iterator {
next() {
// …
}
}
const myIterator = Iterator.from({
next() {
// …
},
});
Constructor
Iterator()-
Được thiết kế để được mở rộng bởi các lớp khác tạo iterator. Ném lỗi khi được xây dựng độc lập.
Phương thức tĩnh
Iterator.concat()-
Tạo đối tượng
Iteratormới từ danh sách các đối tượng iterable. Iterator mới tạo ra các giá trị từ mỗi iterable đầu vào theo thứ tự. Iterator.from()-
Tạo đối tượng
Iteratormới từ đối tượng iterator hoặc iterable. Iterator.zip()Experimental-
Tạo đối tượng
Iteratormới tổng hợp các phần tử từ nhiều đối tượng iterable bằng cách tạo ra các mảng chứa các phần tử ở cùng vị trí. Iterator.zipKeyed()Experimental-
Tạo đối tượng
Iteratormới tổng hợp các phần tử từ nhiều đối tượng iterable bằng cách tạo ra các đối tượng chứa các phần tử ở cùng vị trí, với khóa được chỉ định bởi đầu vào.
Thuộc tính instance
Các thuộc tính này được định nghĩa trên Iterator.prototype và được chia sẻ bởi tất cả các instance Iterator.
Iterator.prototype.constructor-
Hàm constructor đã tạo đối tượng instance. Đối với các instance
Iterator, giá trị khởi tạo là constructorIterator. Iterator.prototype[Symbol.toStringTag]-
Giá trị khởi tạo của thuộc tính
[Symbol.toStringTag]là chuỗi"Iterator". Thuộc tính này được dùng trongObject.prototype.toString().Note: Không giống
[Symbol.toStringTag]trên hầu hết các lớp tích hợp sẵn,Iterator.prototype[Symbol.toStringTag]có thể ghi được vì lý do tương thích web.
Phương thức instance
Iterator.prototype.drop()-
Trả về đối tượng iterator helper mới bỏ qua số phần tử đã cho ở đầu iterator này.
Iterator.prototype.every()-
Trả về
falsenếu tìm thấy phần tử không thỏa mãn hàm kiểm tra được cung cấp. Ngược lại, nếu iterator cạn kiệt mà không tìm thấy phần tử như vậy, trả vềtrue. Iterator.prototype.filter()-
Trả về đối tượng iterator helper mới chỉ tạo ra những phần tử của iterator mà hàm callback được cung cấp trả về
true. Iterator.prototype.find()-
Trả về phần tử đầu tiên do iterator tạo ra thỏa mãn hàm kiểm tra được cung cấp. Nếu không có giá trị nào thỏa mãn hàm kiểm tra, trả về
undefined. Iterator.prototype.flatMap()-
Trả về đối tượng iterator helper mới lấy từng phần tử trong iterator gốc, chạy qua hàm ánh xạ và tạo ra các phần tử được trả về bởi hàm ánh xạ (chứa trong iterator hoặc iterable khác).
Iterator.prototype.forEach()-
Thực thi hàm được cung cấp một lần cho mỗi phần tử do iterator tạo ra.
Iterator.prototype.map()-
Trả về đối tượng iterator helper mới tạo ra các phần tử của iterator, mỗi phần tử được biến đổi bởi hàm ánh xạ.
Iterator.prototype.reduce()-
Thực thi hàm callback "reducer" do người dùng cung cấp trên mỗi phần tử do iterator tạo ra, truyền giá trị trả về từ phép tính trên phần tử trước đó. Kết quả cuối cùng của việc chạy reducer trên tất cả các phần tử là một giá trị duy nhất.
Iterator.prototype.some()-
Trả về
truenếu tìm thấy phần tử thỏa mãn hàm kiểm tra được cung cấp. Ngược lại, nếu iterator cạn kiệt mà không tìm thấy phần tử như vậy, trả vềfalse. Iterator.prototype.take()-
Trả về đối tượng iterator helper mới tạo ra số phần tử đã cho trong iterator này rồi kết thúc.
Iterator.prototype.toArray()-
Tạo instance
Arraymới được điền bởi các phần tử do iterator tạo ra. Iterator.prototype[Symbol.dispose]()-
Gọi phương thức
return()củathis, nếu nó tồn tại. Điều này triển khai giao thức disposable và cho phép nó được xử lý khi sử dụng vớiusinghayawait using. Iterator.prototype[Symbol.iterator]()-
Trả về chính đối tượng iterator. Điều này cho phép các đối tượng iterator cũng có thể lặp.
Ví dụ
>Sử dụng iterator như iterable
Tất cả các iterator tích hợp sẵn cũng có thể lặp, vì vậy bạn có thể sử dụng chúng trong vòng lặp for...of:
const arrIterator = [1, 2, 3].values();
for (const value of arrIterator) {
console.log(value);
}
// Logs: 1, 2, 3
Đặc tả kỹ thuật
| Specification |
|---|
| ECMAScript® 2027 Language Specification> # sec-%iteratorprototype%-object> |