前言:
关于之前用的for循环遍历数组的缺陷
let colors = ["pink", "red", "gray"];
colors.name = "ccy";
console.log(colors); // ["pink", "red", "gray", name: "ccy"]
// 遍历方法一
for(let i = 0; i < colors.length; i++){
console.log(colors[i]) // 输出:pink red gray
}
// 缺点:不够直观,没有直接操作元素;用来遍历变量不好管理,可能有多个,ijk等等
// 遍历方法二
colors.forEach((item)=>{
// if (item === "red"){
// break;
// }
console.log(item); // 输出:pink red gray
}) // 直接操作元素,但不能提前停止遍历,提前break报错:Illegal break statement
// 遍历方法三
for (let prop in colors){
console.log(colors[prop]); // 输出:pink red gray ccy
} // 缺点,会把不是索引对应值也遍历出来
仿造迭代器的功能,有内置next()函数,指向下一个索引对应的值,返回一个对象。里面包含当前索引值和是否遍历结束;结束遍历的下一个next,当前值设为undefined
let colors = ["pink", "red", "gray"];
colors.name = "ccy";
// 仿造迭代器的功能
function createIterator (arr){
var index = 0;
return {
next(){
return index < arr.length ? {value:arr[index++], done:false} : {value:undefined, done:true}
}
}
}
let iterato = createIterator(colors);
优点:直接操作元素;并且只输出有索引的值;当执行next()时,才向下遍历一项
默认迭代器
目前接触的可迭代的数据结构有:
1.数组Array,
2.类数组(dom元素/arguments),
3.字符串String,
后续还会接触:
4.Map,
5.Set,也是可迭代的
不论是哪种数据结构,迭代器是统一的接口,通过一个键为Symbol.iterator
的方法来实现,使各种数据结构可被便捷的访问
数组Array:
// 数组使用迭代器
let arr = [1,2,3,4];
let arrIt = arr[Symbol.iterator]();
console.log(arrIt); // Array Iterator {}
console.log( arrIt.next() ); // {value: 1, done: false}
console.log( arrIt.next() ); // {value: 2, done: false}
console.log( arrIt.next() ); // {value: 3, done: false}
console.log( arrIt.next() ); // {value: 4, done: false}
console.log( arrIt.next() ); // {value: undefined, done: true}
类数组(dom元素/arguments):
// 类数组使用迭代器
// dom元素
let myP = document.getElementsByTagName("p");
let pIt = myP[Symbol.iterator]();
console.log(pIt); // Array Iterator {}
console.log(pIt.next()); // {value: p, done: false} 第一个p
console.log(pIt.next()); // {value: p, done: false} 第二个p
console.log(pIt.next()); // {value: p, done: false} 第三个p
console.log(pIt.next()); // {value: p, done: false} 第四个p
console.log(pIt.next()); // {value: undefined, done: true}
// arguments
function fn (){
let fnIt = arguments[Symbol.iterator]();
console.log(fnIt); // Array Iterator {}
console.log(fnIt.next());
console.log(fnIt.next());
console.log(fnIt.next());
console.log(fnIt.next());
console.log(fnIt.next());
// 依次输出元素 1 2 3 4 undefined,最后一次输出中的done为true
}
fn(1,2,3,4);
字符串:
// 字符串使用迭代器
let str = "ccy";
let strIt = str[Symbol.iterator]()
console.log(strIt); // StringIterator {}
console.log(strIt.next());
console.log(strIt.next());
console.log(strIt.next());
console.log(strIt.next());
// 依次输出:"c" "c" "y" undefined,最后一次输出的done值为true
普通对象obj不是可迭代的,没有内置迭代器,可以自己写
迭代器的使用场景
1.for…of循环
省去手动next()的麻烦,遍历的变量可满足语义化,可以中断遍历,可迭代的数据结构均可使用for…of
// for ... of
let colors = ["pink", "red", "gray"];
for (let color of colors) {
console.log(color); // 输出 pink yellow
if (color == 'red'){
break;
}
}
2.数组新增方法:keys() / values() / entries()
// 数组新增方法 解构赋值
// keys()
let colors = ["pink", "red", "gray"];
for (let key of colors.keys()){
console.log(key); //输出: 0 1 2
}
// valus()
for (let value of colors.values()){
console.log(value); //输出: pink yellow gray
}
// entries() 解构赋值
for (let [index, item] of colors.entries()){
console.log(index, item); //输出: 0 pink 1 yellow 2 gray
}
解构赋值和扩展运算符(…)的原理也是迭代器