Iteritor迭代器 来看看如何用for of迭代对象每一个属性吧!

135 阅读2分钟

Iterator迭代器

interator迭代器:只是一种机制,可以为各种不同的数据结构提供统一的循环和迭代规范,而for of循环本身就是基于这种进制进行迭代的!

  • 拥有Interator机制的对象,必须具备 next 方法:执行这个方法可以依次访问对象中的每个成员
  • 执行next返回值是一个对象:
    • value:当前迭代的这一项
    • done:记录是否迭代完成
//重写Iterator迭代
class Iterator{
  constructor(assemble){
    let self = this;
    self.assemble = assemble;
    self.index = 0;
  }
  next() {
    let self = this,
        assemble = self.assemble;
    if(self.index > assemble.length - 1){
      return {
        value:undefined,
        done:true
      };
    }
    return{
      value:assemble[self.index++],
      done:false
    };
  }
}
let itor = new Iterator([10,20,30]);
console.log(itor.next()); //->{value:10,done:false}
console.log(itor.next()); //->{value:20,done:false}
console.log(itor.next()); //->{value:30,done:false}
console.log(itor.next()); //->{value:undefined,done:true}

Symbol.iterator

虽然不具备 Iterator 内置类,但是对于某些数据结构,它提供了Symbol.iterator 属性方法,这个方法具备迭代器规范,基于这个方法可以依次迭代数据中的每一项

  • 数组 Array.prototype[Symbol.iterator]=function...
  • Set.prototype / Map.prototype
  • String.prototype
  • NodeList.prototype
  • arguments[Symbol.iterator]
  • generator object
  • ...

把Symbol.iterator方法执行,会返回一个具备迭代器规范的itor对象,基于itor.next()依次执行,就可以获取到数据集合中的每一项!!

Object.prototype上不具备Symbol.iterator,一个普通的对象默认是不能基于迭代器规范循环的

let arr = [10,20,30];
let itor = arr[Symbol.iterator]();
console.log(itor.next()); //->{value:10,done:false}
console.log(itor.next()); //->{value:20,done:false}
console.log(itor.next()); //->{value:30,done:false}
console.log(itor.next()); //->{value:undefined,done:true}

for...of

ES6中新提供的“for...of”循环,就是按照Iterator迭代器机制去迭代的!!

  1. 先去找arr[Symbol.iterator]执行(如果数据集合不具备这个属性,就会报错 ‘Uncaught TypeError: {} is not iterable’),返回一个迭代器对象itor 2.每一轮循环都会执行一次 itor.next()方法,把结果中的value赋值给循环中的value;当done为true时,则结束整个循环!!
let arr = [10,20,30];
arr[Symbol.iterator] = function(){
  let self = this,
      index = 0;
  return {
    next(){
      if(index>self.length - 1){
        return {
          value:undefined,
          done:true
        };
      };
      let result = {
        value:self[index],
        done:false
      };
      index += 2;
      return result
    }
  }
};
for (let value of arr){
  console.log(value);  //依次迭代+2  10,30
}

for...of迭代对象每个属性值

Object.prototype上不具备Symbol.iterator,一个普通的对象默认是不能基于迭代器规范循环的,也就是不能使用for/of

Object.prototype[Symbol.iterator] = function(){
  let self = this,
      keys = Reflect.ownKeys(self),
      index = 0;
  return{
    next(){
      if(index >= keys.length){
        return {
          value:undefined,
          done:true
        };
      }
      return{
        value:self[keys[index++]],
        done:false
      }
    }
  }
}

let obj = { name:'itor',age:13,lx:0};
for(let value of obj){
  console.log(value); // itor,13,0
}

for...of迭代类数组每个值

let obj = {0:10,1:20,2:30,length:3};
obj[Symbol.iterator] = Array.prototype[Symbol.iterator];
for (let value of obj){
  console.log(value); // 10,20,30
}