preface
text
1. Generation, definition and Simulation of iterators
(1) disadvantages of for loop
The disadvantage of the ordinary for loop is that the array has a known length, and each item of the array can be obtained through the index, so the whole array can be traversed by increasing the index. Executing a routine through this loop is not ideal for the following reasons.
A. you need to know how to use the data structure before iteration. Each item in the array can only get the array object by reference, and then get the item at a specific index position by [] operator. This does not apply to all data structures.
b. the traversal order is not inherent in the data structure. Accessing data by incrementing an index is an array type specific way and does not apply to other data structures with implicit order.
(2) generation of iterators
The iterator is an object designed for iteration with a specific interface. The iterator holds an internal pointer to the collection position. Whenever the next() method is called, the iterator will return a result IteratorResult object. The result object has two properties, corresponding to the value of the next value and a boolean type done. Call next() on the last value The return value of the done attribute is true (indicating that there are no more values for use), and the value attribute will be the return value of the iterator itself. The return value is not part of the original data set, but becomes the last part of the relevant data, or use undefined when the iterator does not provide a return value. The return value of the iterator itself is similar to the return value of the function, Is the last resort to return information to the caller.
(3) simulation of iterator
According to the above definition, the iterator function is implemented manually
// createIterator Function returns a next()Object of method,As an iterator, each call next()Method to return a specific IteratorResult Object value function createIterator(items) { var i = 0; return { next() { var done = (i >= items.length); var value = !done ? items[i++] : undefined; return { done, value } } } } var iterator = createIterator([11, 22, 33]) console.log(iterator.next());//{done: false, value: 11} console.log(iterator.next());//{done: false, value: 22} console.log(iterator.next());//{done: false, value: 33} console.log(iterator.next());//{done: true, value: undefined}
2, Iterator patterns and iteratable objects
The Iterator pattern (especially in the context of ECMAScript) describes a scheme that some structures can be called "iteratable objects" because they implement a formal iteratable interface and can be consumed through the Iterator iterator.
(1) access the default iterator symbol.iterator
let values = [1, 2, 3, 4] let iterator = values[Symbol.iterator]() console.log(iterator.next());//{value:1,deno:false} console.log(iterator.next());//{value:2,deno:false} console.log(iterator.next());//{value:3,deno:false} console.log(iterator.next());//{value:4,deno:false} console.log(iterator.next());//{value:undefiend,deno:true}
(2) check whether an object can be used for iteration
let num = 1; let obj = {}; // Both types do not implement iterator factory functions console.log(num[Symbol.iterator]); // undefined console.log(obj[Symbol.iterator]); // undefined let str = 'abc'; let arr = ['a', 'b', 'c']; let map = new Map().set('a', 1).set('b', 2).set('c', 3); let set = new Set().add('a').add('b').add('c'); let els = document.querySelectorAll('div'); // These types all implement iterator factory functions console.log(str[Symbol.iterator]); // f values() { [native code] } console.log(arr[Symbol.iterator]); // f values() { [native code] } console.log(map[Symbol.iterator]); // f values() { [native code] } console.log(set[Symbol.iterator]); // f values() { [native code] } console.log(els[Symbol.iterator]); // f values() { [native code] } // Calling this factory function generates an iterator console.log(str[Symbol.iterator]()); // StringIterator {} console.log(arr[Symbol.iterator]()); // ArrayIterator {} console.log(map[Symbol.iterator]()); // MapIterator {} console.log(set[Symbol.iterator]()); // SetIterator {} console.log(els[Symbol.iterator]()); // ArrayIterator {}
Summary: check whether an object can be used for iteration: typeof object [symbol. Iterator] = = "function". At the same time, it can be concluded that many built-in types implement Iterable interfaces: string, array, mapping, collection, arguments object, NodeList and other DOM collection types.
be careful:
a. Each iterator represents a one-time ordered traversal of the iteratable object. Instances of different iterators are not related to each other, and only iterate over iteratable objects independently.
b. The iterator is not bound to the snapshot of the iteratable object at a certain time, but only uses a cursor to record the process of traversing the iteratable object. If the iteratable object is modified during the iteration, the iterator also reflects the corresponding changes. As follows:
let arr = ['foo', 'baz']; let iter = arr[Symbol.iterator](); let iter2 = arr[Symbol.iterator](); console.log(iter.next()); // { done: false, value: 'foo' } console.log(iter2.next()); // { done: false, value: 'foo' } // Insert values in the middle of the array arr.splice(1, 0, 'bar'); console.log(iter.next()); // { done: false, value: 'bar' } console.log(iter.next()); // { done: false, value: 'baz' } console.log(iter.next()); // { done: true, value: undefined }
3. Iterators used in development
(1) built in iterator of collection
/* entries()The iterator will return a binomial array every time next() is called, which represents the key and value of each element in the collection, For arrays, the first item is a numeric index, For set, the first item is also a value, because its value is also treated as a key, For a map, the first item is the key */ let arr = [1, 2, 3] console.log(arr.entries());//Array Iterator [] for (const item of arr.entries()) { console.log(item); }// [0:1],[1:2],[2:3] let set = new Set([1, 2, 3]) console.log(set.entries());//SetIterator {[1=>1],[2=>2],[3=>3]} for (const item of set.entries()) { console.log(item); }// [1:1],[2:2],[3:3] let map = new Map() map.set("first", "firseetValue") map.set("second", "seondValue") map.set("third", "thirdValue") console.log(map.entries());//MapIterator {["first"=>"firseetValue"],["second"=>"seondValue"],["third"=>"thirdValue"]} for (const item of map.entries()) { console.log(item); }// ["first":"firseetValue"],["second":"seondValue"],["third":"thirdValue"]
(2) iterator of string
// The characters in the access string can be in the form of subscripts let message = "a b" console.log(message[0])// 'a' let info = "a b" for (const c of info) { console.log(c); }//a, ,b
4. User defined function implementation iterator
// And Iterable The interface is similar to any implementation Iterator All objects of the interface can be used as iterators. class Counter { constructor(limit) { this.limit = limit; } [Symbol.iterator]() { let count = 1,// Put the counter variable into the closure and return to the iterator through the closure,Enables an iteratable object to create multiple iterators, and each iterator created corresponds to a new counter limit = this.limit; return { next() { if (count <= limit) { return { done: false, value: count++ }; } else { return { done: true, value: undefined }; } }, // Optional return() Method is used to specify the logic to execute when the iterator closes prematurely return() { console.log('Exiting early'); return { done: true }; } }; } } let counter = new Counter(3); for (let i of counter) { console.log(i); } // 1 // 2 // 3 for (let i of counter) { console.log(i); } // 1 // 2 // 3 let counter2 = new Counter(5); try { for (let i of counter2) { if (i > 2) { throw 'err'; } console.log(i); } } catch (e) { } // 1 // 2 // Exiting early
Write at the end
The above is the whole content of this article. I hope to bring some help and progress to readers. If it is convenient, pay attention. Xiaobai's growth path will continue to update some common problems and technical points in his work.