迭代器概述: 遍历器(Iterator)是一个接口机制 ,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
特性: ES6 创造了一种新的遍历命令 for...of 循环,Iterator 接口主要供 for...of 消费; 原生具备 iterator 接口的数据(可用 for of 遍历):Array; Arguments; Set; Map; String; TypedArray; NodeList;
工作原理:
1. 创建一个指针对象,指向当前数据结构的起始位置;
2. 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员;
3. 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员;
4. 每调用 next 方法返回一个包含 value 和 done 属性的对象;
-
value表示当前的值,done表示是否遍历完成,布尔值
-
当遍历结束时(最后一个值的next)value为undefined,done返回true
迭代器的基本使用:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>迭代器</title>
</head>
<body>
<script>
// 声明一个数组
const xiyou = ['孙悟空', '猪八戒', '沙僧'];
// 使用 for...of 遍历数组
for(let v of xiyou){
console.log(v);
}
let iterator = xiyou[Symbol.iterator]();
// 调用对象的next方法
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
// 重新初始化对象,指针也会重新回到最前面
let iterator1 = xiyou[Symbol.iterator]();
console.log(iterator1.next());
</script>
</body>
</html
迭代器自定义遍历对象:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>迭代器自定义遍历数据</title>
</head>
<body>
<script>
// 声明一个对象
const banji = {
name: "三年二班",
stus: [
'xiaoming',
'xiaoning',
'xiaotian',
'xiaoku'
],
[Symbol.iterator]() {
// 索引变量
let index = 0;
// 保存this
let _this = this;
return {
next: function() {
if (index < _this.stus.length) {
const result = {
value: _this.stus[index],
done: false
};
// 下标自增
index++;
// 返回结果
return result;
} else {
return {
value: undefined,
done: true
};
}
}
};
}
}
// 遍历这个对象
for (let v of banji) {
console.log(v);
}
</script>
</body>
</html>
生成器概述: 生成器函数是 ES6 提供的一种异步编程解决方案
它是个状态机,封装了各个阶段的数据
用来生成遍历器对象
创建时在function与函数名之间加星号表示generator函数
惰性加载,执行next才执行到函数内的yield语句处
手写生成器函数:
function* myGenerator(){
console.log('开始执行')
let step1 = yield 'step1'
console.log(step1)
console.log('中断后重新执行')
yield console.log('step2')
console.log('完成')
return 'end'
}
//执行generator函数返回一个遍历器对象, 指向初始位置
let iterator = myGenerator()
//执行next方法使遍历器对象指向第一个yield处,yield语句的表达式结果就是value值
console.log(iterator.next()) //'开始执行' {value: 'step1', done: false}
//执行next方法使遍历器对象指向下一个yield处,yield语句的表达式结果就是value值
//可以给next传递实参,这个实参会赋值给执行此next方法时遍历器对象指向的起始yield语句的返回值,此处就是变量step1
console.log(iterator.next('aaa'))//'aaa' '中断后重新执行' 'step2' {value: 'undefined', done: false}
//继续执行next会使返回的value与函数内return的表达式值相同
console.log(iterator.next())//'完成' {value: 'end', done: true}
let obj = {
*[Symbol.iterator](){
yield 1
yield 2
yield 3
}
}
for(let i of obj){
console.log(i)
}
生成器的基本使用:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>生成器</title>
</head>
<body>
<script>
// 生成器其实就是一个特殊的函数
// 异步编程 纯回调函数 node fs ajax mongodb
// yield:函数代码的分隔符
function* gen() {
console.log(111);
yield '没有耳朵';
console.log(222);
yield '没有尾部';
console.log(333);
yield '奇怪';
console.log(444);
}
let iterator = gen();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log("遍历:");
//遍历
for(let v of gen()){
console.log(v);
}
</script>
</body>
</html>
生成器的函数参数传递:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>生成器函数的参数传递</title>
</head>
<body>
<script>
function * gen(arg){
console.log(arg);
let one = yield 111;
console.log(one);
let two = yield 222;
console.log(two);
let three = yield 333;
console.log(three);
}
let iterator = gen("AAA");
console.log(iterator.next()); // 会执行yield 111;
// next()方法是可以传入参数的,传入的参数作为第一条(上一条)语句yield 111的返回
结果
console.log(iterator.next("BBB")); // 会执行yield 222;
console.log(iterator.next("CCC")); // 会执行yield 333;
console.log(iterator.next("DDD")); // 继续往后走,未定义;
</script>
</body>
</html>
生成器函数的2个应用实例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>生成器函数实例1</title>
</head>
<body>
<script>
// 异步编程 文件操作 网络操作(ajax,request) 数据库操作
// 需求:1s后控制台输出111 再过2s后控制台输出222 再过3s后控制台输出333
// 一种做法:不推荐
// setTimeout(()=>{
// console.log(111);
// setTimeout(()=>{
// console.log(222);
// setTimeout(()=>{
// console.log(333);
// },3000)
// },2000)
// },1000)
// 另一种做法
function one(){
setTimeout(()=>{
console.log(111);
iterator.next();
},1000)
}
function two(){
setTimeout(()=>{
console.log(222);
iterator.next();
},1000)
}
function three(){
setTimeout(()=>{
console.log(333);
iterator.next();
},1000)
}
function * gen(){
yield one();
yield two();
yield three();
}
// 调用生成器函数
let iterator = gen();
iterator.next();
</script>
</body>
</html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>生成器函数实例2</title>
</head>
<body>
<script>
// 模拟获取: 用户数据 订单数据 商品数据
function getUsers(){
setTimeout(()=>{
let data = "用户数据";
// 第二次调用next,传入参数,作为第一个的返回值
iterator.next(data); // 这里将data传入
},1000);
}
function getOrders(){
setTimeout(()=>{
let data = "订单数据";
iterator.next(data); // 这里将data传入
},1000);
}
function getGoods(){
setTimeout(()=>{
let data = "商品数据";
iterator.next(data); // 这里将data传入
},1000);
}
function * gen(){
let users = yield getUsers();
console.log(users);
let orders = yield getOrders();
console.log(orders);
let goods = yield getGoods();
console.log(goods); // 这种操作有点秀啊!
}
let iterator = gen();
iterator.next();
</script>
</body>
</html>