JS进阶3-迭代器 生成器

迭代器(Iterator)

ES6引入概念是一种迭代或遍历数据结构的新机制 迭代器是带有特殊接口的对象

可迭代对象

为统一集合类型,es6 引入了iterable类型,Array,Map Set及strings 都是可迭代对象

具有iterable类型的集合都可以通过for..of循环来遍历

 默认情况下定义的对象(Object)是不可迭代的,但是可以通过Symbol.Iterator创建迭代器


迭代器和可迭代对象之间的关系:

可迭代对象都有默认的迭代器和Symbol.iterator属性 

通过使用Symbol.iterator属性来访问对象的默认迭代器

let arr=[1,2,3,4];
let itr=arr[Symbol.iterator]();//Object [Array Iterator] {}
console.log(itr.next());//{ value: 1, done: false }  迭代一次
console.log(itr.next());//{ value: 2, done: false }
console.log(itr.next());
console.log(itr.next());
console.log(itr.next()); //{ value: undefined, done: true }  
//数组里面几个值+1才能调用完迭代器 
//相当于如下
for(let i of arr){
  console.log(i); // 1 2 3 4
}
console.log(itr);

 obj对象生成迭代器


let obj = {
  start: 1,
  end: 5,
  [Symbol.iterator]() {
    return this;
  },
  next() {
    if (obj.start <= obj.end) {
      return { value: obj.start++, done: false };
    } else {
      return { done: true };
    }
  },
};

//如何将对象字面量 创建可迭代对象;
// 第一具有键值为Symbol.iterator的方法,返回一个可迭代对象
//第二对象字面量要拥有next()方法
// obj[Symbol.iterator]=function(){
//    const iterator={
//      next(){
//        if(obj.start <= obj.end){
//          return {value:obj.start++,done:false};
//        }else{
//          return{done:true};
//        }
//      },
//    };
//    return iterator;
// }

for (let i of obj) {
  console.log(i)
}

 迭代器的目的:

使数据结构可迭代

array map set Strings等集合已经可以迭代。当你期望创建的对象能使用for..of循环时需要为对象创建迭代器

如何创建迭代器:

第一具有键值为Symbol.iterator的方法,返回一个可迭代对象
第二对象字面量要拥有next()方法

//for in 和 for of 的区别

//for in 和 for of 都可以循环数组,for in 输出的是数组的index下标
而for of 输出的是数组的每一项的值。


const arr=[1,2,3,4];
//for ...in
for(const key in arr){
  console.log(key) // 0  1 2 3  //遍历下标
}

for(const key of arr){
  console.log(key) //1 2 3 4  //遍历值
}
//区别二:for in 可以遍历对象,for of 不能遍历对象,只能遍历带有iterator接口的,例如Set,Map,String,Array
const obj={people:'zt',age:999}
//for in 
for(const key in obj ){
  console.log(key) //people  age
  console.log(obj[key])// zt 
}

for(const key of obj ){
  console.log(key) //obj is not iterable
}

//数组对象

const list =[{name:'zt',age:100},{name:'tt',age:13}];

for (const val of list){
   console.log(val) //{ name: 'zt', age: 100 }  //{ name: 'tt', age: 13 }
}

for (const val in list){
  console.log(val)  //0  1
  
}

javascript原生遍历方法的建议用法:

  • 用for循环遍历数组
  • 用for-in遍历对象
  • 用for-of遍历类数组对象(ES6)
  • 用Object.keys()获取对象属性名的集合

 2生成器 函数

是ES6 提供一种异步编程解决方案 使得代码书写更优雅

生成器可以再函数执行当中暂停和恢复代码

特点:通常编写函数返回单个值,生成器是一种分阶段返回多个值的函数

执行生成器函数后生成一个可迭代对象

生成器语法 function 关键字 和函数名直接有个*

yield 是一个暂停生成器的操作符

yield也是一个表达式 可以接收输入和发送输出

//生成器函数
// function* fn(){};
// function *fn(){};
// function * fn(){};
// function*fn(){};

const genFunction=function* (){
  console.log("1");
  yield "yieldValue"; //暂停函数   { value: 'yieldValue', done: false }
  console.log("2");
  yield;
  console.log("3");
};

const gObj=genFunction();
console.log(gObj) //Object [Generator] {}
// console.log(gObj.next()) //{ value: 'yieldValue', done: false }
gObj.next(); //1
gObj.next();//2
gObj.next(); //3

for(let o of gObj){
  console.log(o); // 1  2  3
}



//展开运算符
const gObjs=[...genFunction()];
console.log(gObjs) //1  2   3  [ 'yieldValue', undefined ]

//生成器 最适合 与迭代器 一起使用


//生成器 最适合 与迭代器 一起使用

// let obj = {
//   start: 1,
//   end: 5,
//   [Symbol.iterator]:function* () {
//      for(let counter=this.start;counter <= this.end;counter++){
//        yield counter;
//      }
//   },
// };

let obj = {
  start: 1,
  end: 5,
  *[Symbol.iterator]() {
     for(let counter=this.start;counter <= this.end;counter++){
       yield counter;
     }
  },
};




for( let i of obj){
  console.log(i) // 1 2  3  4  5 
}

当递归函数或者被另一个生成器函数调用的时候,使用yield*语法  终止return

// yield*

function* gen1(){
  console.log('hello');
}

// function* gen2(){
//   const gen=gen1();
//   gen.next();
  
// }

function* gen2(){
  yield*gen1();
}

const g2=gen2();
g2.next(); // hello


//阶乘
function* fact(){
  //if
  //exit
  yield* fact();
}

//return 方法
function* re1(){
  yield '1';
  yield '2';
}
const gObj=re1();
console.log(gObj.next()); //{ value: '1', done: false }
// console.log(gObj.next());//{ value: '2', done: false }
console.log(gObj.return());//{ value: undefined, done: true }
console.log(gObj.next()); //{ value: undefined, done: true }



生成器 finally    禁止return 对于生成器的终止执行 一把与try 一起使用

function* gen(){
  try{
    yield '1';
    yield '2';

  }finally{ //finally的内容 就算进行return 也会被执行
     yield "finally";
  }
}
const gObj=gen();
console.log(gObj.next());
console.log(gObj.return());

throw(); 在生成器 函数中 最后暂停的yield的位置抛出异常

function* gen(){
  try{
    yield '1';
    yield '2';

  }catch (error){
    console.log('Error:'+error);
  }
}
const gObj=gen();
console.log(gObj.next());

console.log(gObj.throw()); //Error:undefined  { value: undefined, done: true }

生成器函数为我们提供了一个可以暂停进程并在一段事件后执行的方法

语法:

function关键字与函数名之间有一个*号;

yield 被用于暂停执行;

Next 第一个next调用相当于启动生成器;

Next()方法将函数指针从上次挂起的位置移动到下一行

Return()它终止生成器函数

Throw()他可以帮助我们使用生成器对象抛出错误

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值