迭代器(iterator)

129 阅读1分钟

迭代器概念

const iterator = {
  // 迭代器是一个对象内部实现next(只能有0或1个参数)
  next() {
    // 且需要返回一个对象(内部包含done、value)
    return { done: false, value: '11' }
  }
};

// 数组迭代器思路
const names = ['苏苏', '土狗', 'SharkDog'];

const arrIterator = {
  next() {
    return { done: false, value: '苏苏' };
    return { done: false, value: '土狗' };
    return { done: false, value: 'SharkDog' };
    // 当下次再读取数组值发现已经读取完了后done为true
    // return { done: true, value: undefined }
    return { done: true }; // 此时value可不写
  }
};

数组迭代器

const nums = [1, 2, 3, 5, 8];
const names = ['苏苏', '土狗', 'SharkDog'];

function arrIterator(arr) {
  let index = 0;

  return {
    next() {
      if (index < arr.length) return { done: false, value: arr[index++] };
      else return { done: true }; // 读取不到后value可有可无所以这里选择无
    }
  }
};

const numsIterator = arrIterator(nums);
const nameIterator = arrIterator(names);

console.log(numsIterator.next());
console.log(numsIterator.next());
console.log(numsIterator.next());
console.log(numsIterator.next());
console.log(numsIterator.next());
// 再往后访问就没了
console.log(numsIterator.next());
console.log(numsIterator.next());

console.log(nameIterator.next());
console.log(nameIterator.next());
console.log(nameIterator.next());
// 再往后访问就没了
console.log(nameIterator.next());
console.log(nameIterator.next());

无限迭代器

let index = 0;

const infinityIterator = {
  next() {
    return { done: false, value: index++ };
  }
};
console.log(infinityIterator.next());
console.log(infinityIterator.next());
console.log(infinityIterator.next());

可迭代对象(iterable)[注意和迭代器是有区别的]

const iterableObj = {
  names: ['苏苏', '土狗', 'SharkDog'],
  [Symbol.iterator]: function () {
    let index = 0;

    return {
      next: () => {
        if (index < this.names.length) return { done: false, value: this.names[index++] };
        else return { done: true }; // 读取不到后value可有可无所以这里选择无
      }
    }
  }
};
const iterator = iterableObj[Symbol.iterator]();
const iterator2 = iterableObj[Symbol.iterator]();

console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());

// console.log(iterableObj[Symbol.iterator]().next());

console.log(iterator2.next());
console.log(iterator2.next());
console.log(iterator2.next());
console.log(iterator2.next());

// 不可迭代
// const obj = { name: '苏苏', age: 18 };
// for (const iterator of obj) {
//   console.log(iterator);
// };

// 可迭代(本质上就是调next判断done是否为真返回value)
for (const iterator of iterableObj) {
  console.log(iterator);
};

默认存在迭代器类型(因为对象不存在所以出现了可迭代对象的概念)

const str = '默认存在(Symbol.iterator)';
const names = ['苏苏', '土狗', 'SharkDog'];
const set = new Set([1, 2, 3, 5, 8, 13, 21]);

const arrIterator = names[Symbol.iterator]();
console.log(arrIterator.next());
console.log(arrIterator.next());
console.log(arrIterator.next());
console.log(arrIterator.next());

// 可迭代对象String、Array、Set、Map、arguments、NodeList(获取到的元素集合)
for (const strIterator of str) console.log(strIterator);
for (const arrIterator of names) console.log(arrIterator);
for (const setIterator of set) console.log(setIterator);

function foo() {
  for (const argIterator of arguments) console.log(argIterator);
};
foo(1, 7, 5, 8, 2, 3);

可迭代对象应用场景

const str = '默认存在(Symbol.iterator)';
const names = ['苏苏', '土狗', 'SharkDog'];
const set = new Set([1, 2, 3, 5, 8, 13, 21]);
const obj = { name: '苏苏', age: 18 };

// 扩展
console.log(...str);
console.log({ ...str });
console.log([...str]);

console.log(...names);
console.log({ ...names });
console.log([...names]);

console.log(...set);
console.log({ ...set });
console.log([...set]);

// 特殊的object(看似可以用其实本质上底层用的不是迭代器)
console.log({ ...{ name: '土狗' }, ...obj });

// 解构
const [f, , , , , , , , , , , , , , , , , , , , l] = str;
console.log(f, l);

const [first, , last] = names;
console.log(first, last);

const [one, , , , , , seven] = set;
console.log(one, seven);

// 特殊的object(看似可以用其实本质上底层用的不是迭代器);
const { name, age } = obj;
console.log(name, age);

定义可迭代类

class SelfInfo {
  constructor(address, roomName, person) {
    this.address = address;
    this.roomName = roomName;
    this.person = person;
  };

  entry(newPerson) {
    this.person.push(newPerson);
  };

  [Symbol.iterator]() {
    let index = 0;

    return {
      next: () => {
        if (index < this.person.length) return { done: false, value: this.person[index++] };
        else return { done: true };
      },
      return() {
        console.info('迭代器被干预了!');

        return { done: false };
      }
    }
  }
};
const info = new SelfInfo('合肥', 'E5-1804', ['苏苏', '土狗', 'SharkDog']);
info.entry('安安');

for (const iterator of info) console.log(iterator);
for (const iterator of info) {
  if (iterator == '土狗') continue;
  if (iterator == 'SharkDog') break;

  console.log(iterator);
};