1. 迭代器
1. 定义:
迭代器就是一种机制。它是一种接口,为各种不同的数据结构提 供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
2.
原生具备
iterator
接口的数据
(
可用
for of 遍历【ES6
创造了一种新的遍历命令
for...of
循环,
Iterator
接口主要供
for...of
消费】)
- Array
- Arguments
- Set ( new Set( ) )
- Map( new Map( ) )
- String
- TypedArray
- NodeList
3.
工作原理
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
- 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
- 每调用 next 方法返回一个包含 value 和 done 属性的对象
注: 需要自定义遍历数据的时候,要想到迭代器。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 声明一个数组
const arr = ['ansk', 'youzi', 'yusheng'];
// for of 遍历
for (let v of arr) {
console.log(v); // ansk youzi yusheng , 如果是 in 打印 0 1 2
}
let iterator = arr[Symbol.iterator]();
// 调用对象的next方法
console.log(iterator.next()); // {value: 'ansk', done: false}
console.log(iterator.next()); // {value: 'youzi', done: false}
console.log(iterator.next()); // {value: 'yusheng', done: false} done为true表示遍历已经完成
</script>
</body>
</html>
自定义迭代器,遍历数据:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>自定义遍历数据</title>
</head>
<body>
<script>
const obj = {
name: 'yusheng',
age: 28,
stus: [
'youzi',
'ansk',
'goat',
'fanyu'
],
[Symbol.iterator]() {
let index = 0;
let _this = this;
return {
next: function () {
if (index < _this.stus.length) {
const result = { value: _this.stus[index], done: false };
index++;
return result;
} else { // 执行完毕,value 值为 undefined 且 done 值为 true
return { value: undefined, done: true }
}
}
}
}
}
// 遍历这个对象 for of
for (let v of obj) {
console.log(v);
}
</script>
</body>
</html>
2. 生成器
1. *
的位置没有限制
2.
生成器函数返回的结果是迭代器对象,调用迭代器对象的
next
方法可以得到 yield 语句后的值
3. yield
相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次
next 方法,执行一段代码
4. next
方法可以传递实参,作为
yield
语句的返回值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>生成器</title>
</head>
<body>
<script>
// 生成器其实就是一个特殊的函数
// 异步编程 回调函数
// yield 函数代码的分隔符,把代码分成几块
function* gen() {
console.log(111);
yield 'hello';
console.log(222);
yield 'hi';
console.log(333);
yield '你好';
console.log(444);
}
let iterator = gen();
iterator.next(); // 111
iterator.next(); // 222
iterator.next(); // 333
iterator.next(); // 444
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
// 111
// {value: 'hello', done: false}
// 222
// {value: 'hi', done: false}
// 333
// {value: '你好', done: false}
// 444
// {value: undefined, done: true}
for (let v of gen()) {
console.log(v); // 打印 yield 后面的值
}
</script>
</body>
</html>
生成器传参:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>生成器函数参数</title>
</head>
<body>
<script>
function* gen(arg) {
console.log(arg);
let one = yield 111;
console.log(one); // BBB
let two = yield 222;
console.log(two); // CCC
let three = yield 333;
console.log(three); // DDD
}
// 执行获取迭代器对象
let iterator = gen('AAA');
console.log(iterator.next());
// next 方法可以传入实参
console.log(iterator.next('BBB'));// 第2次调用next()传入的实参将作为第1个yield返回的结果
console.log(iterator.next('CCC'));// 第3次调用next()传入的实参将作为第2个yield返回的结果
console.log(iterator.next('DDD'));// 第4次调用next()传入的实参将作为第3个yield返回的结果
</script>
</body>
</html>
3. 练习
生成器练习:
要求: 1 s 后控制台输出 111,2 s 后控制台输出 222, 3 s 后控制台输出 333
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>生成器函数实例</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);
// ES6 写法:
function one() {
setTimeout(() => {
console.log(111);
iterator.next();
}, 1000);
}
function two() {
setTimeout(() => {
console.log(222);
iterator.next();
}, 2000)
}
function three() {
setTimeout(() => {
console.log(333);
iterator.next();
}, 3000)
}
function* gen() {
yield one();
yield two();
yield three();
}
// 调用生成器函数
let iterator = gen();
iterator.next();
</script>
</body>
</html>