上文提到的for...of不能遍历对象的属性,原因是对象的属性是无序的,在设计对象的时候没有加入Iterator迭代器
可迭代的对象有:String、Array、TypedArray、Map 和 Set,这些对象(或者它原型链上的某个对象)必须有一个键为 iterator 的属性
迭代器是可迭代对象(或其原型链上的一个方法),可通过[Symbol.iterator]()
来调用到它;该方法返回一个对象,返回对象的原型上有next()
方法;通过next()
方法来遍历最初的可迭代对象。
next
的返回值是包含value
和done
属性的一个对象;value
是迭代的值,done是迭代的状态
let arr = ['a', 'b', 'c']; let step = arr[Symbol.iterator](); console.log(step);//Array Iterator {} console.log(step.next());//{value: "a", done: false} console.log(step.next());//{value: "b", done: false} console.log(step.next());//{value: "c", done: false} console.log(step.next());//{value: undefined, done: true}
给对象添加自定义迭代器,使用for...of访问
let name = 'zs'; let age = 14; let person1 = { name, age, [Symbol.iterator]: function () { let _this = Object.keys(this); let index = 0; return { next: () => { let value = { key: _this[index], value: this[_this[index]] } let done = (index >= _this.length); index++; return { value, done } } } } } for (let v of person1) { console.log(v); } //Object { key: "name", value: "zs" } //Object { key: "age", value: 14 }
Generator生成器对象是由一个 generator function 返回的
这个函数的声明如下
function* gen() { yield 1; yield 2; yield 3; } let g = gen();//g 就是Generator生成器对象
生成器对象和迭代器对象一样,有一个next方法,用于返回一个由yield
表达式生成的值
g.next(); // "Object { value: 1, done: false }" g.next(); // "Object { value: 2, done: false }" g.next(); // "Object { value: 3, done: false }" g.next(); // "Object { value: undefined, done: true }"
如果想在一个Generator函数里调用另一个Generator函数,需要用到yield*
关键字
function* gen2() { yield 'start' yield* gen(); yield 'end'; } let g2 = gen2();
Set
对象允许你存储任何类型的唯一值(除了不可迭代对象以外),无论是原始值或者是对象引用
Set
对象是值的集合,你可以按照插入的顺序迭代它的元素。 Set中的元素只会出现一次,即 Set 中的元素是唯一的
let arr1 = [1,2,2,4,6,4] function removeRepeat(arr) { return Array.from(new Set(arr)); } removeRepeat(arr1);//[1, 2, 4, 6]
var mySet = new Set([1,2,3]); console.log(s.size);//3
用来向一个 Set
对象的末尾添加一个指定的值;可以链式调用;
mySet.add('abc'); console.log(mySet);//Set(4) {1, 2, 3, "abc"}
用来清空一个 Set
对象中的所有元素;mySet.clear();
可以从一个 Set
对象中删除指定的元素;mySet.delete(value);
返回一个布尔值来指示对应的值value是否存在Set对象中;mySet.has(value);
entries:返回一个新的迭代器对象 ,这个对象的元素是类似 [value, value] 形式的数组
由于set对象不像Map对象那样拥有 key,然而,为了与 Map 对象的 API 形式保持一致;所以set的key和value是相同的值
keys/values:返回一个新的迭代器对象,该对象包含Set
对象中的按插入顺序排列的所有元素的值
let mySet = new Set([1, 2, 3]); mySet.add('abc') console.log(mySet.entries());//SetIterator {1 => 1, 2 => 2, 3 => 3, "abc" => "abc"}
Map 对象保存键值对,并且能够记住键的原始插入顺序。任何值(对象或者原始值) 都可以作为一个键或一个值。
let map1 = new Map([['name', 'zs'],['age',19]]); console.log(map1.size);
map1.get(key)
map1.set(key, value)
Map
对象中存在该元素,则移除它并返回 true
;否则如果该元素不存在则返回 false
map1.delete(key)
map1.clear()
map1.has(key)
entries:返回一个新的包含 [key, value]
对的 Iterator
对象,返回的迭代器的迭代顺序与 Map
对象的插入顺序相同
keys:返回一个新的 Iterator
对象。它包含按照顺序插入 Map
对象中每个元素的key值
values:返回一个新的Iterator对象。它包含按顺序插入Map对象中每个元素的value值
let map2 = new Map(); map1.set('0', 'foo'); map1.set(1, 'bar'); let iterator1 = map1.entries(); let iterator2 = map1.keys(); let iterator3 = map1.keys(); console.log(iterator1.next().value);// ["0", "foo"] console.log(iterator1.next().value);// [1, "bar"] console.log(iterator2.next().value);// "0" console.log(iterator2.next().value);// 1 console.log(iterator3.next().value);// "foo" console.log(iterator3.next().value);// "bar"