1: 什么是可迭代对象?

1: 可迭代对象具有Symbol.iterator属性
2: Symbol.iterator是一个方法
3: Symbol.iterator的返回值是一个迭代器
4: 结合以上第二点和第三点,可以得出Symbol.iterator就是一个生成器

所以我们可以给出一个可迭代对象的明确定义就是:一个对象,具有Symbol.iterator属性,Symbol.iterator是一个生成器函数,那么这个对象就是可迭代对象

2: 如何创建一个可迭代对象?
有了上面的第一点的定义,我们就可以创建出一个可迭代对象,如下:

let myIteratorObject = {
    items: [],
    *[Symbol.iterator](){
        for(let item of this.items){
            yield item;
        }
    }
};

myIteratorObject.items = [1, 2, 3];
for(let item of myIteratorObject){
    console.log(item);//依次得到1, 2, 3
}

3: ES6默认的可迭代对象有哪些?
从前面的内容我们知道,并不是所有的对象都是可迭代对象,我们自己创建的对象,必须要手动添加*[Symbol.iterator]这个生成器才行。但是ES6内建的对象,有一些默认就是可迭代对象,毋需我们再做额外的工作。它们就是以下这些:

1: 数组Array
2: Set
3: Map
4: 字符串String
5: NodeList(准确说来是定义在DOM标准中)

4: 集合对象(Array, Set, Map)的内建迭代器有几种?
从上面的第三点我们知道Array, Set, Map它们默认就是可迭代对象,这说明它们默认就有迭代器。而这三个集合对象,不仅有默认迭代器,而且还不止1个,有3个:

1: entries() 返回一个迭代器,其值为多个键值对
2: values()  返回一个迭代器,其值为集合的值
3: keys()    返回一个迭代器,其值为集合中的所有键名

下面通过代码来来看一下使用这三种不同的集合所对应的三种不同的迭代器得到的数据是什么:

let array = [1, 2, 3];
let set = new Set(['a', 'b', 'c']);
let map = new Map();
map.set('name', 'apple');
map.set('price', 20);

//entries()
for (let item of array.entries()) {
    console.log(item);
}
for (let item of set.entries()) {
    console.log(item);
}
for (let item of map.entries()) {
    console.log(item);
}
//values()
for(let item of array.values()){
    console.log(item);
}
for(let item of set.values()){
    console.log(item);
}
for(let item of map.values()){
    console.log(item);
}

//keys()
for(let item of array.keys()){
    console.log(item);
}
for(let item of set.keys()){
    console.log(item);
}
for(let item of map.keys()){
    console.log(item);
}

entries()

[0, 1]
[1, 2]
[2, 3]
["a", "a"]
["b", "b"]
["c", "c"]
["name", "apple"]
["price", 20]

values()

1
2
3
a
b
c
apple
20

keys()

0
1
2
a
b
c
name
price

从以上结果我们看出,

1: 对于Array来说,会把元素下标作为每一个“键值对”的key;
2: 对于Set来说,集合元素本身既是key,又是value;
3: Map就是最标准的key就是key,value就是value啦。

5: 集合对象的默认迭代器是什么?
从上面的第4点我们知道了,Array,Set,Map这三种集合对象都内建了三种不同的迭代器,但是如果当我们在使用for...of的时候,不是十分确定地指定某一种迭代器,那这三个对象会默认使用哪个呢?

let array = [1, 2, 3];
let set = new Set(['a', 'b', 'c']);
let map = new Map();
map.set('name', 'apple');
map.set('price', 20);
for(let item of array){
    console.log(item);
}
for(let item of set){
    console.log(item);
}
for(let item of map){
    console.log(item);
}

我们会得到以下结果:

1
2
3
a
b
c
["name", "apple"]
["price", 20]

所以结论就是:

1: Array的默认迭代器是values()
2: Set的默认迭代器是values()
3: Map的默认迭代器是entries()

6: 可迭代对象的初级使用场景

1:用于for...of
2:用于展开运算符...

for...of和展开运算符都要求作用的对象是可迭代对象。for...of我们就不再赘述,前面的例子里面已经有用到;接下来看一下展开运算符的代码示例:

let map = new Map([['name', 'apple'],['price', 20]]);
let array = [...map];
for(let item of array){
    console.log(item)
}

得到结果:

["name", "apple"], ["price", 20]

以上我们通过for...of迭代array的元素,得到两个一维数组,由此可知array本身是一个二维数组:[['name', 'apple'],['price', 20]],也就是和传给new Map()的参数的数组一样。这是因为展开运算符会使用作用对象的默认迭代器(对于Map来说,就是多对键值对)然后,把这些键值对,依次放入数组中。


nanaistaken
583 声望43 粉丝