JS(13)—— 一文搞懂迭代器【Iterator】和生成器【Generator】

114 阅读4分钟

迭代器

迭代器

迭代器 是一种对象类型,它提供了一个统一的方式来遍历集合中的元素。

它包含两个必要的方法:next() 和 return()

  • next() 方法在迭代器内部执行时,返回一个对象,包含两个属性:done和 value,用于描述迭代是否已经结束,以及返回的当前元素值。
  •  return() 方法用于中断迭代器的操作。
// 定义迭代器
function createIterator(items) {
  let i = 0;
  return {
    next: function() {
      let done = i >= items.length;
      let value = !done ? items[i++] : undefined;
      return {
        done: done,
        value: value
      }
    }
  };
}

const iterator = createIterator([1, 2, 3]);
console.log(iterator.next().value); // 1
console.log(iterator.next().value); // 2
console.log(iterator.next().value); // 3

可迭代对象 and Symbol.iterator属性

可迭代对象 实现了 Iterable接口的对象,即可以被迭代器进行迭代消费操作的对象

  • 可迭代对象都会暴露一个键名为 Symbol.iterator 的属性

        - 该属性的值为迭代器工厂函数,且调用该函数会返回一个`迭代器`
    
         * [ Symbol.iterator]() {
            return {
                next: function() {
                let done = i >= items.length;
                let value = !done ? items[i++] : undefined;
                return {
                    done: done,
                    value: value
                   }
                }
              };
          }
          
           const array = [1, 2, 3];
           const iterator = array[Symbol.iterator]();
           
           console.log(iterator.next()); // { value: 1, done: false }
           console.log(iterator.next()); // { value: 2, done: false }
           console.log(iterator.next()); // { value: 3, done: false }
    
    
  • 一些内置的可迭代对象

       - 字符串
       - 数组
       - 映射 、 集合
       - arguments对象
       - NodeList 
    
  • 实际过程中不需要显示的调用上述工厂函数,一些原生语言会自动帮我们调用!!!

     - for - of
     - 数组结构
     - 扩展符
     - Array.from()
     - 创建映射 、集合
     - yield* 操作符
    

all in all

可迭代对象,都会有 Symbol.iterator属性 ,该属性的值是一个迭代器创建函数,即执行该函数会返回一个可以迭代该对象的迭代器,这个迭代器是个对象,且有 next()return() 方法。

生成器

生成器

生成器本质是一种特殊类型的函数,使用 function* 声明,并且可以在函数体内使用 yield 关键字来暂停函数的执行并返回一个值。

生成器对象

生成器对象是调用生成器函数产生的返回值。它跟迭代器对象有异曲同工之妙,它也实现了Iterator接口。但是,与迭代器不同,生成器对象具有更灵活的控制能力。除了使用 next() 方法来向前执行,还可以使用 return() 方法来提前终止生成器函数,并返回指定的值。还可以使用 throw() 方法来在生成器函数内部引发异常

function* generateValues() {
  yield 1;
  yield 2;
  yield 3;
}

const generator = generateValues();

console.log(generator.next()); // { value: 1, done: false }
console.log(generator.return(4)); // { value: 4, done: true }

yield 关键字 【只能在生成器函数中使用】

yield 关键字是用于定义生成器函数的特殊关键字,它可以在函数体内指示函数的执行暂停并返回一个值,同时可以在后续调用生成器对象的 next() 方法时恢复函数的执行。下面是一个使用 yield 关键字生成数据的示例:

yield* 表达式来在函数体内嵌套另一个可迭代对象。跟其他的一起按顺序迭代!!

function* generateValues() {
  yield 1;
  yield 2;
  yield 3;
  yield* [4, 5, 6];
}

const generator = generateValues();

console.log(generator.next()); // { value: 1, done: false }
console.log(generator.next()); // { value: 2, done: false }
console.log(generator.next()); // { value: 3, done: false }
console.log(generator.next()); // { value: 4, done: false }
console.log(generator.next()); // { value: 5, done: false }
console.log(generator.next()); // { value: 6, done: false }
console.log(generator.next()); // { value: undefined, done: true }

可以使用 yield 关键字实现输入和输出:

  • 数据的输入: 上一次让生成器函数暂停的 yield 关键字会收到传给 next() 方法的第一个参数!!![ 即此时,yield 相当于一个变量来接收参数]
function* generator() {
const a = yield; 
yield a * 2; 
}
const iterator = generator(); // 使用 next 方法启动生成器函数,并暂停在第一个 yield 语句 iterator.next(); // 将值 3 传递给生成器函数,并恢复执行 const { value } = iterator.next(3); console.log(value); // 6

- **数据的输出:**  yiled 后面的值 x ,会出现在调用 next( ) 方法后,返回的对象中 { done : false , value : x }
function* generator() {
  yield 'apple';
  yield 'orange';
  yield 'banana';
}

const iterator = generator();

console.log(iterator.next()); // { value: 'apple', done: false }
console.log(iterator.next()); // { value: 'orange', done: false }
console.log(iterator.next()); // { value: 'banana', done: false }
console.log(iterator.next()); // { value: undefined, done: true }

return() 和 throw()

  • return( )

    • 传给 return() 方法的值 x,会出现在调用 return() 方法返回的对象中 { done : ture , value : x}
  • throw( )

    • throw() 方法会把一个错误注入到生成器对象中,如果错误被捕获处理了,生成器就不会发生中断, 会继续进行,如果未被处理,生成器函数就会中断进行!!!
    • 并且如果处理了,生成器会跳过 此时的yiled ,即会跳过一个值!!!(p204)