先说结论:
- 推荐在循环对象属性的时候,使用for...in,在遍历数组的时候的时候使用for...of
- for...in循环出的是key,for...of循环出的是value
- for…of是ES6新增的遍历方式,它提供了统一的遍历机制。所有实现了[Symbol.iterator]接口的对象都可以被遍历。
- for...of不能循环普通的对象,需要通过和Object.keys()搭配使用
for in循环
for…in 用于遍历对象所有的可枚举属性,功能类似于Object.keys()。
let obj = {
name: 'jbangit',
phone: '13800138000'
}
for (let prop in obj) {
console.log(prop);
}
像constructor,数组的length等就属于不可枚举属性。
你可以通过Object.defineProperty()定义一个属性,决定它是否可枚举。
Iterator和for...of循环
在ES6中新增了Set和Map两种数据结构,再加上JS之前原有的数组和对象,这样就有了四种数据集合,平时还可以组合使用它们,定义自己的数据结构,比如数组的成员是Map,Map的成员是对象等。这样就需要一种统一的接口机制,来处理所有不同的数据结构。
Iterator就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制
Iterator和for...of循环关系
数组已经部署了iterator接口,ES6新增了遍历命令for...of循环,for...of调用Iterator接口消费。
给一个普通对象部署iterator接口
let obj = {
data: [ 'hello', 'world' ],
[Symbol.iterator]() {
const self = this;
let index = 0;
return {
next() {
if (index < self.data.length) {
return {
value: self.data[index++],
done: false
};
} else {
return { value: undefined, done: true };
}
}
};
}
};
注意:
1:Symbol.iterator是个函数
2:返回一个next函数
3:next函数返回一个对象包含value和done两个属性
使用for of遍历对象
for (var key of Object.keys(obj)) {
console.log(key + ': ' + obj[key]);
}
其中Object.keys(obj) 一个表示给定对象的所有可枚举属性的字符串数组。
可枚举
可枚举性(enumerable)用来控制所描述的属性,是否将被包括在for...in循环之中。具体来说,如果一个属性的enumerable为false,下面三个操作不会取到该属性。
- for..in循环
- Object.keys方法
- JSON.stringify方法
for...in循环和Object.keys方法的区别,在于前者包括对象继承自原型对象的属性,而后者只包括对象本身的属性。如果需要获取对象自身的所有属性,不管enumerable的值,可以使用Object.getOwnPropertyNames方法