Js 迭代器高级用法

269 阅读3分钟

Js 迭代器高级用法

JavaScript中的迭代器是一种强大的工具,可以用于遍历和处理集合中的元素。迭代器提供了许多高级用法,可以更加灵活和有效地处理数据。在本篇文章中,将介绍15个用于迭代器的高级用法,以便开发者更好地理解和应用这一概念。

1. 自定义迭代器

使用Symbol.iterator可以为对象定义自定义迭代器。

const myObject = {
    data: ['Apple', 'Banana', 'Orange'],
    [Symbol.iterator]() {
        let index = 0;

        return {
            next: () => {
                if (index < this.data.length) {
                    return { value: this.data[index++], done: false };
                } else {
                    return { done: true };
                }
            }
        };
    }
};

for (const item of myObject) {
    console.log(item);
}
// 输出: 'Apple', 'Banana', 'Orange'

2. 生成迭代器

可以使用Generator函数生成一个迭代器。

function* myGenerator() {
    yield 'Apple';
    yield 'Banana';
    yield 'Orange';
}

const generator = myGenerator();

console.log(generator.next().value); // 输出: 'Apple'
console.log(generator.next().value); // 输出: 'Banana'
console.log(generator.next().value); // 输出: 'Orange'

3. 双向迭代器

使用for...of语句可以双向迭代器(如SetMap)中的元素。

const mySet = new Set(['Apple', 'Banana', 'Orange']);

for (const item of mySet) {
    console.log(item);
}
// 输出: 'Apple', 'Banana', 'Orange'

4. 迭代器链

多个迭代器可以链接起来形成一个大的迭代器链。

const fruits = ['Apple', 'Banana', 'Orange'];
const iterator1 = fruits[Symbol.iterator]();
const iterator2 = fruits[Symbol.iterator]();
const combinedIterator = {
    next() {
        const { value, done } = iterator1.next();
        if (!done) {
            return { value, done };
        } else {
            return iterator2.next();
        }
    }
};

for (const item of combinedIterator) {
    console.log(item);
}
// 输出: 'Apple', 'Banana', 'Orange'

5. 取部分元素

使用slice方法可以从迭代器中取出部分元素。

const numbers = [1, 2, 3, 4, 5];
const iterator = numbers[Symbol.iterator]();
const slicedIterator = {
    next() {
        const { value, done } = iterator.next();
        if (value === 3) {
            return { value, done };
        }
        if (!done) {
            return this.next();
        } else {
            return { done };
        }
    }
};

for (const item of slicedIterator) {
    console.log(item);
}
// 输出: 3

6. 跳过部分元素

使用skip方法可以跳过迭代器中的部分元素。

const numbers = [1, 2, 3, 4, 5];
const iterator = numbers[Symbol.iterator]();
const skippedIterator = {
    next() {
        const { value, done } = iterator.next();
        if (value === 3) {
            return iterator.next();
        }
        return { value, done };
    }
};

for (const item of skippedIterator) {
    console.log(item);
}
// 输出: 1, 2, 4, 5

7. 过滤元素

使用filter方法可以筛选迭代器中符合条件的元素。

const numbers = [1, 2, 3, 4, 5];
const iterator = numbers[Symbol.iterator]();
const filteredIterator = {
    next() {
        let { value, done } = iterator.next();
        while (!done && value % 2 === 0) {
            ({ value, done } = iterator.next());
        }
        return { value, done };
    }
};

for (const item of filteredIterator) {
    console.log(item);
}
// 输出: 1, 3, 5

8. 映射元素

使用map方法可以对迭代器中的元素进行映射操作。

const numbers = [1, 2, 3, 4, 5];
const iterator = numbers[Symbol.iterator]();
const mappedIterator = {
    next() {
        const { value, done } = iterator.next();
        if (!done) {
            return { value: value * 2, done };
        } else {
            return { done };
        }
    }
};

for (const item of mappedIterator) {
    console.log(item);
}
// 输出: 2, 4, 6, 8, 10

9. 合并迭代器

使用zip方法可以合并多个迭代器为一个。

function* zip(iterators) {
    const iteratorsArr = iterators.map(iterator => iterator[Symbol.iterator]());
    while (true) {
        const results = iteratorsArr.map(iterator => iterator.next());
        if (results.some(result => result.done)) {
            return;
        }
        yield results.map(result => result.value);
    }
}

const numbers = [1, 2, 3];
const letters = ['a', 'b', 'c'];
const zipped = zip([numbers, letters]);

for (const item of zipped) {
    console.log(item);
}
// 输出: [1, 'a'], [2, 'b'], [3, 'c']

10. 反向迭代

使用reverse方法可以反向迭代一个迭代器。

function* reverseIterator(iterable) {
    const array = Array.from(iterable);
    for (let i = array.length - 1; i >= 0; i--) {
        yield array[i];
    }
}

const numbers = [1, 2, 3, 4, 5];
const reversed = reverseIterator(numbers);

for (const item of reversed) {
    console.log(item);
}
// 输出: 5, 4, 3, 2, 1

11. 迭代倒计时

使用迭代器可以实现倒计时的效果。

function* countDown(from) {
    while (from >= 0) {
        yield from;
        from--;
    }
}

const countdownIterator = countDown(5);

const countdownInterval = setInterval(() => {
    const { value, done } = countdownIterator.next();
    if (done) {
        clearInterval(countdownInterval);
    } else {
        console.log(value);
    }
}, 1000);

12. 同步迭代异步操作

使用reduce方法可以同步迭代一个异步操作的集合。

const urls = ['url1', 'url2', 'url3'];

async function asyncOperation(url) {
    // 异步操作
    return url;
}

const result = urls.reduce(async (accumulatorPromise, url) => {
    const accumulator = await accumulatorPromise;
    const value = await asyncOperation(url);
    accumulator.push(value);
    return accumulator;
}, Promise.resolve([]));

result.then(console.log);
// 输出: ['url1', 'url2', 'url3']

13. 合并异步操作结果

使用Promise.all方法可以将多个异步操作的结果进行合并。

const urls = ['url1', 'url2', 'url3'];

async function asyncOperation(url) {
    // 异步操作
    return url;
}

const result = await Promise.all(urls.map(asyncOperation));

console.log(result);
// 输出: ['url1', 'url2', 'url3']

14. 处理异步操作异常

在迭代异步操作时,可以使用try...catch语句处理异常。

const urls = ['url1', 'url2', 'url3'];

async function asyncOperation(url) {
    if (url === 'url2') throw new Error('Operation failed.');
    return url;
}

async function processUrls(urls) {
    for (const url of urls) {
        try {
            const result = await asyncOperation(url);
            console.log(result);
        } catch (error) {
            console.error(error);
        }
    }
}

processUrls(urls);

15. 并行处理异步操作

通过使用Promise.all方法和map方法,可以并行处理一组异步操作。

const urls = ['url1', 'url2', 'url3'];

async function asyncOperation(url) {
    // 异步操作
    return url;
}

async function processUrls(urls) {
    const results = await Promise.all(urls.map(asyncOperation));
    console.log(results);
}

processUrls(urls);
// 输出: ['url1', 'url2', 'url3']