Iteration methods for collection types
ECMAScript 6 introduced new collection types (such as Set
, Map
, WeakSet
, and WeakMap
) and provided them with various iteration methods. These methods make traversing collection elements more flexible and efficient while maintaining high consistency with traditional array iteration approaches.
Iteration Methods for Set
Set
is an unordered collection with unique elements. ES6 provides the following iteration methods for Set
:
forEach Method
Set.prototype.forEach
allows executing a callback function for each element in the set, with syntax similar to the array's forEach
:
const mySet = new Set([1, 2, 3]);
mySet.forEach((value, valueAgain, set) => {
console.log(value); // 1, 2, 3
});
Note: In Set
's forEach
, the second parameter valueAgain
is the same as the first parameter. This is to maintain consistency with Map
's forEach
.
keys, values, and entries Methods
Set
provides the following iterator-generating methods:
const mySet = new Set(['a', 'b', 'c']);
// keys() returns an iterator of values
for (const key of mySet.keys()) {
console.log(key); // 'a', 'b', 'c'
}
// values() is the same as keys()
for (const value of mySet.values()) {
console.log(value); // 'a', 'b', 'c'
}
// entries() returns an iterator in the form of [value, value]
for (const entry of mySet.entries()) {
console.log(entry); // ['a', 'a'], ['b', 'b'], ['c', 'c']
}
Direct Iteration of Set
Objects
Set
objects themselves are iterable, and their default iterator is the same as values()
:
const mySet = new Set([true, false]);
for (const item of mySet) {
console.log(item); // true, false
}
Iteration Methods for Map
Map
is a collection of key-value pairs, and its iteration methods are more extensive than those of Set
:
forEach Method
Map.prototype.forEach
can traverse all key-value pairs:
const myMap = new Map([
['name', 'Alice'],
['age', 25]
]);
myMap.forEach((value, key, map) => {
console.log(`${key}: ${value}`); // "name: Alice", "age: 25"
});
keys, values, and entries Methods
const myMap = new Map([
[1, 'one'],
[2, 'two']
]);
// keys() returns an iterator of keys
for (const key of myMap.keys()) {
console.log(key); // 1, 2
}
// values() returns an iterator of values
for (const value of myMap.values()) {
console.log(value); // 'one', 'two'
}
// entries() returns an iterator in the form of [key, value]
for (const entry of myMap.entries()) {
console.log(entry); // [1, 'one'], [2, 'two']
}
Direct Iteration of Map
Objects
The default iterator for Map
is the same as entries()
:
const myMap = new Map([[false, 'no'], [true, 'yes']]);
for (const [key, value] of myMap) {
console.log(key, value); // false 'no', true 'yes'
}
Special Characteristics of WeakSet
and WeakMap
WeakSet
and WeakMap
do not provide any iteration methods because their keys are weakly referenced. The JavaScript engine may reclaim these objects at any time, making it impossible to guarantee stable iteration.
const weakSet = new WeakSet([{}, {}]);
// weakSet.forEach(...) // Error: weakSet.forEach is not a function
const weakMap = new WeakMap();
// for (const item of weakMap) {...} // Error: weakMap is not iterable
Combining Iterators with Destructuring Assignment
Collection iterators can be perfectly combined with destructuring assignment:
const userMap = new Map([
['id', 123],
['name', 'Bob'],
['email', 'bob@example.com']
]);
// Convert to an array for processing
const userArray = [...userMap];
console.log(userArray); // [['id', 123], ['name', 'Bob'], ['email', 'bob@example.com']]
// Directly destructure key-value pairs
for (const [key, value] of userMap) {
console.log(`User ${key}: ${value}`);
}
Custom Iteration Logic
By returning custom iterators, you can control the iteration behavior of collections:
class CustomSet extends Set {
*filter(predicate) {
for (const value of this) {
if (predicate(value)) {
yield value;
}
}
}
}
const numbers = new CustomSet([1, 2, 3, 4, 5]);
for (const num of numbers.filter(x => x % 2 === 0)) {
console.log(num); // 2, 4
}
Performance Considerations
Different iteration methods may have performance variations on large collections:
const largeMap = new Map();
for (let i = 0; i < 1000000; i++) {
largeMap.set(i, `value${i}`);
}
// Test for...of speed
console.time('for...of');
for (const [key, value] of largeMap) {
// Empty loop
}
console.timeEnd('for...of');
// Test forEach speed
console.time('forEach');
largeMap.forEach((value, key) => {
// Empty callback
});
console.timeEnd('forEach');
Typically, for...of
performs similarly to forEach
in the latest JavaScript engines, but there may be differences across browsers.
Integration with Other ES6 Features
Collection iterators can be combined with features like generators and asynchronous iteration:
async function* asyncMapValues(map) {
for (const value of map.values()) {
// Simulate asynchronous operation
yield await Promise.resolve(value);
}
}
const asyncMap = new Map([[1, 'A'], [2, 'B']]);
(async () => {
for await (const value of asyncMapValues(asyncMap)) {
console.log(value); // 'A', 'B'
}
})();
Common Usage Patterns
Collection iteration methods have various applications in real-world development:
- Data Transformation:
const setToArray = [...new Set([1, 2, 2, 3])]; // [1, 2, 3]
- Map Conversion:
const mapToObject = Object.fromEntries(
new Map([['a', 1], ['b', 2]]).entries()
); // {a: 1, b: 2}
- Filtering Operations:
const filteredMap = new Map(
[...originalMap].filter(([key, value]) => value > 10)
);
- Batch Operations:
function bulkSetOperation(setA, setB, operation) {
const result = new Set();
for (const item of setA) {
if (operation === 'union' || setB.has(item)) {
result.add(item);
}
}
return result;
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn