概念:
遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历 *** 作
在JS中,Iterator接口可以通俗的理解为对象的属性,属性的名字为symbol.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 属性的对象;
注:需要自定义遍历数据的时候,要想到迭代器;
// 声明一个数组,因为数组具备Iterator属性
const xiyou = ["唐僧", "孙悟空", "猪八戒", "沙僧"];
// 使用for...of遍历数组
for (let v of xiyou) {
console.log(v);
}
以上代码输出结果为下图片,因为我们数组具有Iterator接口,所以可以直接使用for...of进行遍历
上述代码还可以采用for...in进行遍历。for...in遍历的结果是键名,即为1,2,3,4......,for...of遍历的结果为键值。
接下来正式解释iterator的工作原理:
1. 创建一个指针对象,指向当前数据结构的起始位置;
let iterator = xiyou[Symbol.iterator]();
2. 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员;
3. 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员;
4. 每调用 next 方法返回一个包含 value 和 done 属性的对象;
调用next方法,next不停的指向下一个成员,当我们的遍历结束之后done的值就变为true.同时value值也变为undefined。每次返回的结果都是一个对像。
// 调用对象的next方法
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
2.迭代器自定义遍历对象
因为对象是不存在iterator这个属性的,所以如下代码遍历的时候会报banji这个对象不能被遍历的错。为了解决该问题,我们自定义遍历对象。
PS:此处会有疑问,为什么我不直接使用for...in遍历呢?for...in遍历时可以的,但是本地方是像使用for...of进行遍历,同时返回的值是我们stus中的一个成员。又有人会有疑问,为什么不直接使用banji.syus.forEach()进行遍历呢?这个方法也是可行的,但是这不符合面向对象 的一种思想。
// 声明一个对象
const banji = {
name: "终极一班",
stus: [
"xiaoming",
"xiaoning",
"xiaotian",
"knight"
]
}
// 遍历改对象
for (let v of banji) {
console.log(v);
}
下面开始我们自定义遍历数据
[Symbol.iterator]() {
}
加入上述代码遍历之后会报如下错误:
报没有对象的错,既然没有对象,那我们就返回一个对象。
[Symbol.iterator]() {
return {};
}
但是加了对象之后依旧会报上述错误,报undefined不是一个函数的错误的原因是因为我们iterator属性中有一个next的方法,而我们代码中没有,为了解决此问题,我们创建一个next方法。
[Symbol.iterator]() {
return {
next: function () {
}
};
}
添加上述代码后依旧会报错,报错为我们迭代器返回的结果是一个undefined,这个undefined不是一个对象。这是因为我们的next每次返回的结果都应该是包含value和done属性的一个对象。但是我们上述代码没有value和done属性。为了解决此问题我们添加这两个属性。
next: function () {
return {
value: "aaa",
done: false
}
}
添加上述代码不会报错,但是会一直运行,怕cpu承受不住,此处不截图了。之所以会出现一直输出,没有停止的现象是因为我们每次调用next都会返回done为false的状态,那就表示我们对象没有被遍历完,需要一直遍历。那么为了解决这个问题我们就要对返回的结果进行处理。
return {
next: () => {
if (index < this.stus.length) {
const result = { value: this.stus[index], done: false };
// 下标自增
index++;
// 返回结果
return result;
} else {
return { value: undefined, done: true }
}
}
};
添加以上代码可以完成我们想通过iterator对对象进行的一个遍历。
完整的代码如下:
// 声明一个对象
const banji = {
name: "终极一班",
stus: [
"xiaoming",
"xiaoning",
"xiaotian",
"knight"
],
[Symbol.iterator]() {
// 先声明一个索引变量
let index = 0;
return {
next: () => {
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);
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)