循环、遍历、迭代
for in 主要是针对对象进行遍历的,比如:object
、array
,typeof [] 为 object,一种特殊的对象,不能对 new Map()
和 new Set()
进行遍历。
可以看 MDN 的描述:
- for...in 语句以任意顺序遍历一个对象的除 Symbol 以外的可枚举属性。
- for...in 不应该用于迭代一个关注索引顺序的 Array。
- 如果你只要考虑对象本身的属性,而不是它的原型,那么使用 hasOwnProperty() 来确定某属性是否是对象本身的属性
除了 for in
还有一个类似的 循环方法 for of
,它主要用于在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环。
for of
是依赖于迭代器,而这个迭代器就是 Symbol.iterator
,那哪一些类型具备这个迭代器能够使用 for of
呢?
Array.prototype[@@iterator]() // 包括 arguments
TypedArray.prototype[@@iterator]()
String.prototype[@@iterator]()
Map.prototype[@@iterator]()
Set.prototype[@@iterator]()
注意:Object
不具备 Symbol.iterator
迭代器
Symbol.iterator 的属性特性:
- writable: false
- configurable: false
- enumerable: false
for of 和 for in 的差别
for in:
- 遍历是无序的
- 针对于 Object,Array 也可用,Map 和 Set 不可用
- 遍历可枚举的属性,包含原型上的属性,可以使用 hasOwnProperty 处理自身属性
- 遍历得到的 item 是键名
for of:
- 遍历是有序的
- 针对于存在迭代器(Symbol.iterator)的类型,比如:Array、TypedArray、String、Map、Set
- 不可遍历与 Object,因为它没有迭代器
- 遍历得到的 item 是键值
自定义迭代器
// 自定义迭代器,Symbol.iterator
// 对于 Object 是没有内置迭代器 Symbol.iterator 的,所以无法使用 for of 去迭代,因为 for of 依赖于迭代器 Symbol.iterator
// 先看一下遍历迭代器的流程是怎么样的
// ----------- 迭代器流程 Start -----------
const iterator = function* generator(arr) {
let index = 0;
while (index < arr.length) {
yield arr[index++];
}
}
// 开始迭代
const _iterator = iterator([1, 2, 3]); // 执行迭代器,得到 generator 对象,包含 next 方法
console.log(_iterator.next()); // {value: 1, done: false}
console.log(_iterator.next()); // {value: 2, done: false}
console.log(_iterator.next()); // {value: 3, done: false}
console.log(_iterator.next()); // {value: undefined, done: true} // 判断为 done 为 true,不在执行
// 以上就是一个迭代过程,像 for of 迭代的时候,内部就是调用 next,如果 done 为 true 就不在输出 value,并且停止调用 next
// ----------- 迭代器流程 End -----------
// ES6 方式自定义迭代器
Object.prototype[Symbol.iterator] = function* () {
let index = 0;
while (index < this.length) {
yield this[index++];
}
};
// ES6以前方式自定义迭代器
Object.prototype[Symbol.iterator] = function () {
let index = 0;
const _this = this;
return {
next() {
return index < _this.length ? { value: _this[index++], done: false } : {value: undefined, done: true}
}
}
};
const obj = {
0: 1,
1: 2,
2: 3,
length: 3
}
for (let val of obj) {
console.log(val);
}
// 输出: 1 2 3
// for of 的内部就是先调用 Object.prototype[Symbol.iterator] 得到迭代器对象,
// 然后根据 done 是否为 true,如果不是则不断去 next,知道 done 为 true 则停止迭代
// 这里有一点,使用 generator 的时候为什么 while 的条件不直接为 while(true){} 不断循环让迭代去 next 内,
// 首先要知道,迭代的时候是根据返回的 done 为 true 才停止的,那对于 generator 函数,
// 什么时候才返回 done 为 true 呢,那就是没有 yield 预等待输出的时候,如果设置为 while(true){},
// 那么 done 永远都为 false,for of 迭代的时候,将不会停止。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!