迭代器和生成器
一.迭代器
1.迭代器是带有特别接口的对象
,返回一个next
要领,该要领中同时又value
和done
属性,当再没有值能够迭代时,value
为undefined
,done
为true
,不然value
为当前值,done
为false
2.依据上面的形貌完成一个迭代器,以下:
let iterator = {
i: 0,
items: [2, 4, 6],
next() {
let value, done;
done = (this.i === this.items.length);
value = done ? undefined : this.items[this.i++];
return {
value: value,
done: done
}
}
};
console.log(iterator.next()); //{value: 2, done: false}
console.log(iterator.next()); //{value: 4, done: false}
console.log(iterator.next()); //{value: 6, done: false}
console.log(iterator.next()); //{value: undefined, done: true}
二.生成器
1.生成器是返回迭代器的函数,以下:
function *createIterator() {
yield 1;
yield 2;
yield 3;
}
let iterator = createIterator();
console.log(iterator.next()); //{value: 1, done: false}
console.log(iterator.next()); //{value: 2, done: false}
console.log(iterator.next()); //{value: 3, done: false}
console.log(iterator.next()); //{value: undefined, done: true}
2.生成器有几点要注意的:
- 当实行流碰到yield语句时,该生成器就住手运转了,直到迭代器再次挪用next
- 能够再for轮回中运用yield
- yield只能用在生成器的内部,即使是生成器内部的函数也不可,即:yield没法逾越函数边境
- 没法运用箭头函数建立生成器
- 生成器能够存在于对象的属性中
三.for-of轮回
1.可迭代范例:指那些包括Symbol.iterator
属性的对象,该属性定义了返回迭代器的函数(如:数组,set,map等)
2.for-of轮回能够轮回可迭代范例,for-of轮回会在可迭代范例每次实行后挪用next()并将效果存储在变量中,轮回会延续举行,直到效果对象的done属性为true
3.for-of轮回会挪用数组的Symbol.iterator
属性来猎取迭代器(该要领由幕后的js引擎挪用),并将挪用iterator.next(),并将该效果对象的value属性的值赋给num,直到done为true,轮回会退出,num不会被赋给undefined,代码以下:
let values = [1, 2, 3];
for (let item of values) {
console.log(item); //1 2 3
}
4.关于非可迭代对象,如null
和undefined
,运用for-of轮回会抛出毛病
5.能够在for-of轮回中运用解构
let map = new Map();
map.set('name', 'sxt');
map.set('age', 2);
for(let [key, value] of map) {
console.log(key + " = " + value);
}
//输出:
//name = sxt
//age = 2
6.for-of轮回能够用于轮回NodeList
四.Symbol.iterator
1.能够用Symbol.iterator
属性来访问对象默许的迭代器,如:
let arr = [6, 7, 8];
let iterator = arr[Symbol.iterator]();
console.log(iterator.next()); //{value: 6, done: false}
console.log(iterator.next()); //{value: 7, done: false}
console.log(iterator.next()); //{value: 8, done: false}
console.log(iterator.next()); //{value: undefined, done: true}
2.推断一个对象是不是能够迭代,能够经由过程推断Symbol.iterator
属性是不是是一个函数来完成,如:
function isIterator(obj) {
return typeof obj[Symbol.iterator] === 'function';
}
let arr = [1, 3, 4];
let num = 1;
console.log(isIterator(arr)); //true
console.log(isIterator(num)); //false
3.建立可迭代范例: 我们本身定义的对象默许是不可迭代范例,然则我们能够经由过程设置Symbol.iterator
属性来使这个对象能够迭代。由于前面第3点有讲到,推断一个对象是不是能够迭代,实际上是经由过程Symbol.iterator
属性来肯定的,由此能够建立下面的对象
let obj = {
*[Symbol.iterator]() {
yield 1;
yield 2;
yield 3;
}
};
for (let item of obj) {
console.log(item); //1 2 3
}
五.内置迭代器
1.我们寻常迭代数组,set和map时,能拿到迭代的值,是由于这些鸠合中有内置的迭代器,如
let arr = [1, 3, 5];
let set = new Set();
set.add('time');
set.add('user');
set.add('family');
let map = new Map();
map.set('name', 'sxt');
map.set('age', 12);
map.set('sister', 'andy');
for(let item of arr) {
console.log(item); // 1 3 5
}
for(let item of set) {
console.log(item); //time user family
}
for(let item of map) {
console.log(item); //["name", "sxt"] ["age", 12] ["sister", "andy"]
}
2.内置迭代器分为三种
- entries()
- keys()
- values()
3.数组的entries返回的是[索引,值]
,set的entries是[值,值]
,由于set的键值是一样的,map的entries是[键名,键值]
,如:
let arr = [1, 3, 5];
let set = new Set();
set.add('time');
set.add('user');
set.add('family');
let map = new Map();
map.set('name', 'sxt');
map.set('age', 12);
map.set('sister', 'andy');
for(let item of arr.entries()) {
console.log(item); // [0, 1] [1, 3] [2, 5]
}
for(let item of set.entries()) {
console.log(item); //["time", "time"] ["user", "user"] ["family", "family"]
}
for(let item of map.entries()) {
console.log(item); //["name", "sxt"] ["age", 12] ["sister", "andy"]
}
4.数组的keys返回的索引,set的keys返回的照样值,map的keys返回的是值
5.数组,set,map的values返回的都是值
六.向迭代器中通报参数
1.我们能够向迭代器中通报参数
function *createIterator() {
let first = yield 1;
let second = yield first + 2;
yield second + 3;
}
let iterator = createIterator();
console.log(iterator.next()); //{value: 1, done: false}
console.log(iterator.next(4)); //{value: 6, done: false}
console.log(iterator.next(5)); //{value: 8, done: false}
console.log(iterator.next()); //{value: undefined, done: true}
- 这里的难点是明白右边的代码会和左侧的中缀
- 初次挪用next的时刻,不论传入什么参数都会被疏忽,由于传入的参数会作为yield语句的返回值,而第一次只是yield 1,而没有变量
七.包括return语句的生成器
function *createIterator() {
yield 1;
return 133;
yield 2;
yield 3;
}
let iterator = createIterator();
console.log(iterator.next()); //{value: 1, done: false}
console.log(iterator.next(4)); //{value: 133, done: true}
console.log(iterator.next(5)); //{value: undefined, done: true}
console.log(iterator.next()); //{value: undefined, done: true}
- return会让它提早实行终了并针对next的挪用返回一个值
八.生成器代办
1.即,在一个生成器中挪用别的的生成器,有时刻,如许的操纵会越发的有用
function *create1() {
yield 1;
yield 2;
yield 3;
}
function *create() {
yield *create1();
yield true;
}
let iterator = create();
console.log(iterator.next()); //{value: 1, done: false}
console.log(iterator.next()); //{value: 2, done: false}
console.log(iterator.next()); //{value: 3, done: false}
console.log(iterator.next()); //{value: true, done: false}
console.log(iterator.next()); //{value: undefined, done: true}