Js 迭代器高级用法

Js 迭代器高级用法

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

1. 自定义迭代器

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

javascript 复制代码
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函数生成一个迭代器。

javascript 复制代码
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)中的元素。

javascript 复制代码
const mySet = new Set(['Apple', 'Banana', 'Orange']);

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

4. 迭代器链

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

javascript 复制代码
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方法可以从迭代器中取出部分元素。

javascript 复制代码
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方法可以跳过迭代器中的部分元素。

javascript 复制代码
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方法可以筛选迭代器中符合条件的元素。

javascript 复制代码
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方法可以对迭代器中的元素进行映射操作。

javascript 复制代码
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方法可以合并多个迭代器为一个。

javascript 复制代码
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方法可以反向迭代一个迭代器。

javascript 复制代码
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. 迭代倒计时

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

javascript 复制代码
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方法可以同步迭代一个异步操作的集合。

javascript 复制代码
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方法可以将多个异步操作的结果进行合并。

javascript 复制代码
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语句处理异常。

javascript 复制代码
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方法,可以并行处理一组异步操作。

javascript 复制代码
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']
相关推荐
世界哪有真情7 小时前
拿人类意识卡 AI?等于用 bug 验收正式产品
前端·人工智能·后端
Listen·Rain8 小时前
Vue3:setup详解
前端·javascript·vue.js
Patrick_Wilson9 小时前
修好 bug 只是开始:一次由监控需求反向重构日志结构的复盘
前端·监控·数据可视化
kyriewen9 小时前
面试官让我优化一个卡死的表格,我打开 Claude 五秒重写,他放下咖啡问我要不要来当组长
前端·javascript·面试
小粉粉hhh10 小时前
React(二)——dom、组件间通信、useEffect
前端·javascript·react.js
Csvn10 小时前
🤖 AI 生成前端代码的 5 个典型翻车现场及修复指南
前端
IT_陈寒11 小时前
SpringBoot自动装配坑了我一天,原来问题出在这
前端·人工智能·后端
索西引擎12 小时前
【React】key 属性:协调算法中的元素标识机制与最佳实践
前端·javascript·react.js
只会cv的前端攻城狮12 小时前
动态组件架构设计:从配置到事件驱动全链路解析
前端·vue.js
飞天狗12 小时前
Next.js 16 App Router 实战:服务端组件与流式渲染
前端·next.js