适用目标不一样
for..in
可用于遍历可枚举数据,如对象、数组、字符串。
什么是可枚举:属性中的enumerable
值为true
时,就是可枚举的,具体可通过Object.getOwnPropertyDescriptors(o)
来查看。
const p = {
name: "bob",
age: 18
};
console.log(Object.getOwnPropertyDescriptors(p));
// 输出:
{
name: {
value: "bob",
writable: true,
enumerable: true,
configurable: true
},
age: { value: 18, writable: true, enumerable: true, configurable: true }
}
const arr = [1, 2, 3, 4];
console.log(Object.getOwnPropertyDescriptors(arr));
输出:
{
'0': { value: 1, writable: true, enumerable: true, configurable: true },
'1': { value: 2, writable: true, enumerable: true, configurable: true },
'2': { value: 3, writable: true, enumerable: true, configurable: true },
'3': { value: 4, writable: true, enumerable: true, configurable: true },
length: { value: 4, writable: true, enumerable: false, configurable: false }
}
for..of
用于可迭代对象,如:Array
, String
, Map
, Set
, 函数的arguments
,NodeList
可迭代对象是指具有Symbol.iterator
属性的对象,该属性的值为一个函数,返回值是一个迭代器。而迭代器是指具有next
方法的对象,该方法返回一个value
和done
属性的对象。
const arr = [1, 2, 3, 4];
const item = arr[Symbol.iterator]();
console.log(item.next());
console.log(item.next());
console.log(item.next());
console.log(item.next());
console.log(item.next());
输出:
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: 4, done: false }
{ value: undefined, done: true }
遍历范围不一样
for..in
可以遍历原型上的可枚举属性
for..of
默认只有遍历自身的属性,具体和迭代器的实现有关。
//默认实现思路
arr[Symbol.iterator] = function () {
const _this = this;
return {
i: 0,
next() {
return this.i < _this.length ? { value: _this[this.i++], done: false } : { value: undefined, done: true };
}
};
};
//通过自定义迭代器改变输出值
Array.prototype.foo = "aaaaa";
const arr = [1, 2, 3, 4];
arr[Symbol.iterator] = function () {
const _this = this;
//手动修改迭代器的实现方法
Object.keys(this.__proto__).forEach((item) => this.push(this.__proto__[item]));
return {
i: 0,
next() {
return this.i < _this.length ? { value: _this[this.i++], done: false } : { value: undefined, done: true };
}
};
};
for (const value of arr) {
console.log(value);
}
//输出:
1
2
3
4
aaaaa
输出结果不一样
for..in
遍历得到的key
,且不保证顺序
for..of
遍历默认得到的是value
,具体和迭代器实现有关
根据上述代码修改
const arr = [3, 5, 6, 8];
arr[Symbol.iterator] = function () {
const _this = this;
return {
i: 0,
next() {
// return this.i < _this.length ? { value: _this[this.i++], done: false } : { value: undefined, done: true };
return this.i < _this.length ? { value: this.i++, done: false } : { value: undefined, done: true };
}
};
};
for (const value of arr) {
console.log(value);
}
输出:
0
1
2
3