Phương pháp lặp Symbol.iterator
Chào các bạn
Trong bài viết này mình sẽ nói về phương pháp lặp [Symbol.iterator]().
Symbol.iterator là gì ?
Symbol.iterator là một phương thức lặp cho phép các đối tượng trong javascript tùy chỉnh hành vi lặp đi lặp lại của chúng.
Để có thể lặp đối tượng tìm và gọi phương pháp [Symbol.iterator]()
1let str = "Hồ Quang Trí"; 2 3let iterator = str[Symbol.iterator]();
iterator
iterator là đối tượng có phương pháp next() dùng để lặp đi lặp lại nhiều lần.
1let str = "Hồ Quang Trí"; 2 3let iterator = str[Symbol.iterator](); 4 5console.log(iterator.next()); // {done: false, value: "H"}
Nếu bây giờ chúng ta gọi phương pháp next tiếp.
1let str = "Hồ Quang Trí"; 2 3let iterator = str[Symbol.iterator](); 4 5console.log(iterator.next()); // {value: 'H', done: false} 6console.log(iterator.next()); // {value: 'ồ', done: false}
Và cứ như vậy cho đến khi done: true
1let str = "Hồ Quang Trí"; 2 3let iterator = str[Symbol.iterator](); 4 5console.log(iterator.next()); // {value: 'H', done: false} 6console.log(iterator.next()); // {value: 'ồ', done: false} 7console.log(iterator.next()); // {value: ' ', done: false} 8console.log(iterator.next()); // {value: 'Q', done: false} 9console.log(iterator.next()); // {value: 'u', done: false} 10console.log(iterator.next()); // {value: 'a', done: false} 11console.log(iterator.next()); // {value: 'n', done: false} 12console.log(iterator.next()); // {value: 'g', done: false} 13console.log(iterator.next()); // {value: ' ', done: false} 14console.log(iterator.next()); // {value: 'T', done: false} 15console.log(iterator.next()); // {value: 'r', done: false} 16console.log(iterator.next()); // {value: 'í', done: false} 17console.log(iterator.next()); // {value: undefined, done: true}
Vòng lặp
Như các bạn có thể thấy ở trên mỗi lần chạy nó đều tìm và gọi phương pháp next
1let str = "Hồ Quang Trí"; 2 3let iterator = str[Symbol.iterator](); 4 5while (true) { 6 let {value, done} = iterator.next(); // Gọi next 7 if(done) { 8 break; 9 } 10 console.log(value); // H, ..., í 11}
Chúng ta có thể lặp nó bằng for of
1let str = "Hồ Quang Trí"; 2 3for(let v of str) { 4 console.log(v); // H, ..., í 5}
Giả sử bây giờ chúng ta ghi đè phương pháp [Symbol.iterator]() thì xem nó như thế nào nhé
1let str = "Hồ Quang Trí"; 2 3String.prototype[Symbol.iterator] = null; // Ghi đè nó 4 5for(let v of str){ // Uncaught TypeError: str is not iterable 6 console.log(v); 7}
Ở ví dụ trên các bạn nếu chưa học thì sẽ chưa biết String.prototype là gì đúng không?. Đến bài nào đó mình sẽ nói về cái này.
Từ ví dụ trên nếu chúng ta ghi đè Symbol.iterator nó thì bây giờ lỗi đả văng ra. Các bạn nên đọc tin nhắn của lỗi nó rất quan trọng. Và tin nhắn lỗi là str is not iterable. Hiểu đơn giản là nó không có cái iterator mà chúng ta đang học nè.
Sau vòng lặp này chúng ta biết. Mỗi lần for of chạy nó sẽ tìm và gọi phương pháp [Symbol.iterator]().
Tương tự với mảng
1let arr = [1, 2, 3]; 2 3let iterator = arr[Symbol.iterator](); 4 5console.log(iterator.next()); // {value: 1, done: false} 6console.log(iterator.next()); // {value: 2, done: false} 7console.log(iterator.next()); // {value: 3, done: false} 8console.log(iterator.next()); // {value: undefined, done: true}
Nếu chúng ta ghi đè nó.
1let arr = [1, 2, 3]; 2 3Array.prototype[Symbol.iterator] = null; 4 5for(let v of arr) { // Uncaught TypeError: arr is not iterable 6 console.log(v); 7}
Làm việc với Object
Giả sử bây giờ chúng ta có một đối tượng như thế này.
1let obj = { 2 from: 1, 3 to: 5 4};
Bây giờ chúng ta muốn lặp từ 1 đến 5. Bình thường chúng ta lặp như thế này.
1let obj = { 2 from: 1, 3 to: 5, 4}; 5 6let { from, to } = obj; 7 8for(let i = from; i <= to; i++){ 9 console.log(i); // 1, 2, 3, 4, 5 10}
Bây giờ chúng ta muốn lặp với for of thì như thế nào?
1let obj = { 2 from: 1, 3 to: 5, 4}; 5 6for(let v of obj) { // Uncaught TypeError: obj is not iterable 7 console.log(v); 8}
Ôi thật không may. Nó không hoạt động. Lỗi đả văng ra. Vậy chúng ta khắc phục nó như thế nào?
1let obj = { 2 from: 1, 3 to: 5, 4 [Symbol.iterator]() { 5 let from = this.from; 6 let to = this.to; 7 8 return { 9 next() { 10 if (from <= to) { 11 return { done: false, value: from++ }; 12 } 13 return { done: true, value: undefined }; 14 }, 15 }; 16 }, 17}; 18 19for (let v of obj) { 20 console.log(v); // 1, 2, 3, 4, 5 21}
Bây giờ nó đã chạy và kết quả như dự tính.
Nó hoạt động hoàn hảo với toán tử lây lan
Dấu 3 chấm ... chính là toán tử lây lan
1let obj = { 2 from: 1, 3 to: 5, 4 [Symbol.iterator]() { 5 let from = this.from; 6 let to = this.to; 7 8 return { 9 next() { 10 if (from <= to) { 11 return { done: false, value: from++ }; 12 } 13 return { done: true, value: undefined }; 14 }, 15 }; 16 }, 17}; 18 19console.log(...obj); // 1, 2, 3, 4, 5
Tổng kết
Trong bài viết này mình đã nói qua về phương pháp lặp [Symbol.iterator](). Các bạn có thể tìm hiểu thêm về nó tại đây iterator
- ký hiệu
- phương pháp
- đối tượng
- vòng lặp