Iterator(迭代器或遍历器)
iterator的概念的使用
iterator的作用:用来提供一种统一的接口机制,来遍历不同的数据结构。
iterator用来遍历集合类型,我们现在了解到的集合类型有:Array,Object,Set,Map
Array,Set和Map可以使用forEach来遍历
Object使用for…in来遍历
这四种集合的遍历方式不同,然后当它们相互组合的时候,会产生各种变化的数据类型:比如数组包对象,对象又包Set等操作。这种操作下的遍历就更加难以统一。
实际使用使用,需要在数据结构上部署默认的iterator接口;然后再通过next调用来使用。
模拟iterator接口:
let arr = ["a", "b", "c", "d"]
function myIterator(arr) {
let index = 0;
return {
next() {
if (index < arr.length) {
return { value: arr[index++], done: false }
} else {
return { value: undefined, done: true }
}
}
}
}
let mi = myIterator(arr)
console.log(mi.next())
console.log(mi.next())
console.log(mi.next())
console.log(mi.next())
console.log(mi.next())
总结:1、过程:创建的是一个指针对象,这个对象指向的是结构中的起始位置,也就是说interator本质上就是一个指针对象,通过调用next(),第一次调用指向的是结构中的第一个成员,第二次调用指向就是结构中的第二个成员,一直到结构结束的位置;
2、返回值:返回的是对象,{value:值,done:false} done为false的时候,表示可以继续循环遍历,为true表示遍历结束{value:undefined,done:true}
在对象上部署iterator接口,如下例:
// Array,Set和Map都默认具备iterator接口,默认接口叫做 Symbol.iterator
// 我们以对象为例,来给对象部署默认iterator接口
let obj = { name: "zhangsan", age: 22, address: "北京" };
// 部署默认接口 Symbol.iterator ;用来访问不同的数据接口,真正实现iterator的功效
obj[Symbol.iterator] = function () {
let keys = Object.keys(this); //[name,age,address]
let index = 0; //记录索引下标
return {
// 箭头函数
next: () => {
if (index < keys.length) {
let key = keys[index++];
return { value: this[key], done: false };
} else {
return { value: undefined, done: true };
}
}
};
};
// 访问默认的接口内容
let iterator = obj[Symbol.iterator]();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
for…of的使用
for。。。of是iterator的语法糖,所以部署了iterator接口的数据集合都可以使用for…of遍历
// 错误的范例:
let obj = { name: "zhangsan", age: 22 };
// 报错,因为obj默认没有部署iterator接口
for (let o of obj) {
console.log(o);
}
or…of相比forEach和for…in的优势在哪里:
1、无法中途跳出forEach循环,break命令或return命令都不能奏效。
2、数组的键名是数字,但是for…in循环是以字符串作为键名“0”、“1”、“2”等等。for…in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键。不安全
3、某些情况下,for…in循环会以任意顺序遍历键名。
总结:for…of适合遍历数组,for…in适合遍历对象
generator(生成器)
generator是一个函数,只不过这个函数的写法比较特殊,在function关键字和函数名之间有一个 * ,这样就构成一个generator生成器;它不是普通的函数,它的调用不会立即执行;调用后返回一个iterator遍历器,每次调用next则执行一步,直到调用结束。return的返回可以立即结束iterator遍历器。
generator意义是什么?
generator内部是一个状态机,可以使用next调用返回多次结果;也可以使用next传递参数给generator函数,来改变函数内部的执行逻辑。
generator内部支持yield表达式,通过调用next,可以让generator内部的yield表达式执行;调用一次执行一次。需要注意的是yield表达式没有返回值(返回undefined);所以下一步的执行需要上一步执行结果的时候,可以使用next传递参数,如下:
function* pow(num) {
let first = yield Math.pow(num, 2);
let second = yield Math.pow(first, 2);
return Math.pow(second, 2);
}
let iterator = pow(2);
let { value: first } = iterator.next();
console.log(first);
let { value: second } = iterator.next(first);
console.log(second);
let { value: third } = iterator.next(second);
console.log(third);
//此时使用for...of不合适,因为没法传递参数
// for (let iterator of pow(2)) {
// console.log(iterator);
// }
aweit
1)await只能出现在async函数中
2)await是等待的意思,等待后面代码执行
3)await后一般是异步代码(一般是异步函数)
4)await后面必须是 promise对象