迭代器和可迭代对象

迭代器

认识什么叫迭代器

维基百科对迭代器的定义:迭代器是确使用户在容器对象上遍访的对象,使用该接口无需关心对象内部实现的细节,维基百科的解释确实很正确,但是他喜欢用概念解释概念,所以说也不好理解。我觉得用大白话来形容:就是迭代器可以帮助我们对某个数据结构进行遍历的对象,在很多语言都有,比如说java、python…

JavaScript中迭代器

  1. 在JavaScript中迭代器也是一个具体的对象,不过这个对象需要符合迭代器协议(iterator protocol)。迭代器协议定义了一系列的值产生的标准。 03_迭代器 - 图1 如果我们阅读英文文档会发现这个位置其实中文翻译的是有问题的,下面这副图才是正确解释 03_迭代器 - 图2
  1. let arr = [1,2,3,4,5]
  2. //符合迭代器协议的对象,可以通过某个标准拿到arr数组中的一个又一个的项,在js中这个标准就是一个特定的next方法
  1. next方法也不是随便定义的一个方法,他也有一定的要求
    • 他是一个无参数或者一个参数的函数,返回一个应当拥有以下两个属性的对象(done、value)
    • 当done的值为false的时候,就代表迭代器可继续产出值,当迭代完毕之后就返回一个true(迭代结束的时候true可以省略)
    • value就是返回false之后需要给使用者返回的值,是最直观的提现,使用者可以拿到这个值进行一系列的操作,当迭代完毕的时候done的值为true,value的值是可选的,如果它存在那么就作为迭代器结束之后的默认值返回。 ```javascript const arr = [1, 2, 3, 4, 5]; let index = 0; const iterableArr = { next() { if (index < arr.length) { return { done: false, value: arr[index++] }; } else { return { done: true, value: undefined }; } }, }; console.log(iterableArr.next()); //{ done: false, value: 1 } console.log(iterableArr.next()); //{ done: false, value: 2 } console.log(iterableArr.next()); //{ done: false, value: 3 } console.log(iterableArr.next()); //{ done: false, value: 4 } console.log(iterableArr.next()); //{ done: false, value: 5 } console.log(iterableArr.next()); //{ done: true, value: undefined } console.log(iterableArr.next()); //{ done: true, value: undefined }

//这样我们就实现了一个简易的迭代器

  1. <a name="ef03596e"></a>
  2. ### 可迭代对象
  3. <a name="5ad4034e"></a>
  4. #### 认识什么叫可迭代对象
  5. 可迭代对象和迭代器完全是两个概念,不能混淆了,可迭代对象需要实现(adorably protocol协议)
  6. 并且返回一个迭代器。
  7. ```javascript
  8. const iterableObj = {
  9. arr: [1, 2, 3, 4, 5],
  10. [Symbol.iterator]() {
  11. let index = 0;
  12. return {
  13. next: () => {
  14. if (index < this.arr.length) {
  15. return { done: false, value: this.arr[index++] };
  16. } else {
  17. return { done: true };
  18. }
  19. },
  20. };
  21. },
  22. };
  23. for (const item of iterableObj) {
  24. console.log(item); //1,2,3,4,5
  25. }

迭代器这种代码,通过调用next去获取数组的每一项,我们在开发中是很少写的,但是这种for..of的代码在开发中是很常见的,for..of可以看做这种语法的语法糖。

可迭代对象的应用

  1. 可以应用于for..of遍历
  2. 也可以引用到展开运算符中
    • 如果是一个对象,那么也是可以的,那么就有一个问题,for..of遍历对象的时候是不可以的,会报错的,例子:
      ```javascript let obj = { name: “coderwei”, age: 19, };

let newObj = { …obj }; console.log(newObj); //{name:’coderwei’,age:19} for (const item of Obj) { console.log(item); //报错 } //展开运算符用在一个对象上原理不是利用可迭代对象,这时ES9提出来的,对对象使用的时候会做特殊的处理,而且展开运算符只能将对象展开到另一个对象。如果展开到数组里依旧会报错:xxx is not iterable

  1. 3. 解构
  2. - 当我们使用解构赋值的时候,本质上也是利用可迭代对象的特性,当前同样要区分解构对象和数组
  3. ```javascript
  4. //解构数组
  5. let arr = [1,2,3]
  6. const [x ,y ,z ] = arr
  7. console.log(x,y,z) //1,2,3
  8. const [x ,z ,y] = arr
  9. console.log(x,y,z) // 1,3,2
  10. //解构对象
  11. let obj = {name:'coderwei',age:19}
  12. const {name,age} = obj
  13. console.log(name.age) //'coderwei',19
  14. const {obj,name} = obj
  15. console.log(name.age) //'coderwei',19
  16. //我们可以发现当我们解构对象的时候,跟定义变量的顺序是无关的,而解构数组则是有关的,也证明了解构数组只是调用迭代器的next方法拿到一个个的value,然后将它赋值给定义的变量

封装一个创建迭代器的函数

  1. function createIterator(arr){
  2. let index = 0
  3. return {
  4. next:function(){
  5. if(index<arr.length){
  6. return {done:false,value:arr[index++]}
  7. }else{
  8. return {done:true,value:undefined}
  9. }
  10. }
  11. }
  12. }
  13. let arr = [1, 2, 3, 4, 5];
  14. let itor = createIterator(arr);
  15. console.log(itor.next()); //{ done: false, value: 1 }
  16. console.log(itor.next()); //{ done: false, value: 2 }
  17. console.log(itor.next()); //{ done: false, value: 3 }
  18. console.log(itor.next()); //{ done: false, value: 4 }
  19. console.log(itor.next()); //{ done: false, value: 5 }
  20. console.log(itor.next()); //{ done: true, value: undefined }
  21. console.log(itor.next()); //{ done: true, value: undefined }