for in, for of, 可枚举,iterator

830 阅读2分钟

先说结论:

  • 推荐在循环对象属性的时候,使用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方法

参考:yanhaijing.com/javascript/…