您好,登录后才能下订单哦!
密码登录
            
            
            
            
        登录注册
            
            
            
        点击 登录注册 即表示同意《亿速云用户服务条款》
        # JavaScript迭代器怎么自定义
## 什么是迭代器
在JavaScript中,**迭代器(Iterator)**是一种特殊的对象,它提供了一种标准的方式来遍历数据集合。迭代器必须实现`next()`方法,该方法返回一个包含`value`和`done`两个属性的对象:
```javascript
const iterator = {
  next() {
    return {
      value: 'some value', // 当前迭代的值
      done: false         // 是否迭代完成
    };
  }
};
JavaScript内置的数据结构(如Array、Map、Set等)都实现了默认的迭代器行为。但在以下场景中,我们可能需要自定义迭代器:
最简单的自定义迭代器方式是直接创建一个满足迭代器协议的对象:
const countdown = {
  value: 3,
  next() {
    if (this.value >= 0) {
      return { value: this.value--, done: false };
    }
    return { value: undefined, done: true };
  }
};
// 使用迭代器
let result = countdown.next();
while (!result.done) {
  console.log(result.value); // 3, 2, 1, 0
  result = countdown.next();
}
更常见的做法是实现可迭代协议,即对象包含一个[Symbol.iterator]方法,该方法返回一个迭代器:
class Countdown {
  constructor(start) {
    this.start = start;
  }
  [Symbol.iterator]() {
    let value = this.start;
    return {
      next: () => {
        if (value >= 0) {
          return { value: value--, done: false };
        }
        return { value: undefined, done: true };
      }
    };
  }
}
// 使用for...of循环
for (const num of new Countdown(3)) {
  console.log(num); // 3, 2, 1, 0
}
ES6的生成器函数可以更简洁地实现迭代器:
function* countdownGenerator(start) {
  for (let i = start; i >= 0; i--) {
    yield i;
  }
}
const countdown = countdownGenerator(3);
for (const num of countdown) {
  console.log(num); // 3, 2, 1, 0
}
class Range {
  constructor(start, end, step = 1) {
    this.start = start;
    this.end = end;
    this.step = step;
  }
  *[Symbol.iterator]() {
    for (let i = this.start; i <= this.end; i += this.step) {
      yield i;
    }
  }
}
for (const num of new Range(1, 10, 2)) {
  console.log(num); // 1, 3, 5, 7, 9
}
class TreeNode {
  constructor(value, children = []) {
    this.value = value;
    this.children = children;
  }
  *[Symbol.iterator]() {
    yield this.value;
    for (const child of this.children) {
      yield* child; // 使用yield*委托给子节点的迭代器
    }
  }
}
const tree = new TreeNode(1, [
  new TreeNode(2, [
    new TreeNode(4),
    new TreeNode(5)
  ]),
  new TreeNode(3)
]);
for (const value of tree) {
  console.log(value); // 1, 2, 4, 5, 3
}
function* fibonacci() {
  let a = 0, b = 1;
  while (true) {
    yield a;
    [a, b] = [b, a + b];
  }
}
const fib = fibonacci();
console.log(fib.next().value); // 0
console.log(fib.next().value); // 1
console.log(fib.next().value); // 1
console.log(fib.next().value); // 2
// 可以无限继续...
可以将多个迭代器组合起来:
function* chain(...iterables) {
  for (const iterable of iterables) {
    yield* iterable;
  }
}
const combined = chain([1, 2], new Set([3, 4]), '56');
for (const value of combined) {
  console.log(value); // 1, 2, 3, 4, '5', '6'
}
function* map(iterable, fn) {
  for (const value of iterable) {
    yield fn(value);
  }
}
function* filter(iterable, predicate) {
  for (const value of iterable) {
    if (predicate(value)) {
      yield value;
    }
  }
}
const numbers = [1, 2, 3, 4, 5];
const squaredEvens = filter(map(numbers, x => x * x), x => x % 2 === 0);
for (const num of squaredEvens) {
  console.log(num); // 4, 16
}
ES2018引入了异步迭代器,用于处理异步数据流:
async function* asyncSequence() {
  for (let i = 1; i <= 3; i++) {
    await new Promise(resolve => setTimeout(resolve, 1000));
    yield i;
  }
}
(async () => {
  for await (const value of asyncSequence()) {
    console.log(value); // 每秒输出1, 2, 3
  }
})();
JavaScript的迭代器协议为自定义遍历逻辑提供了强大的灵活性。通过实现[Symbol.iterator]方法或使用生成器函数,我们可以:
掌握自定义迭代器技巧可以显著提升代码的表达能力和性能,特别是在处理大型或复杂数据结构时。 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。