1.generator生成器函数:
举个🌰例子
function* func() {
console.log('one');
yield 2;
console.log('two');
yield 3;
console.log('end');
}
// 返回一个遍历器对象 可以调用next()
let fn = func();
console.log(fn.next()); //one {value: 2, done: false}
console.log(fn.next()); //two {value: 3, done: false}
console.log(fn.next()); //end {value: undefined, done:true}
🌵小结:
-
调用generator生成器函数后,生成器不会立即执行,仅仅生成一个
迭代器而已,而有了迭代器就可以遍历了,而这个Interator篇讲过 -
generator函数是分段执行的,
yield语句是暂停执行而next()恢复执行
继续举个🌰例子:
function* gen(x){
var y = yield x + 2;
return y;
}
var g = gen(1);
g.next() // { value: 3, done: false }
g.next(2) // { value: 2, done: true }
🌵小结:
- 第一个 next 方法的 value 属性,返回表达式 x + 2 的值(3)。
- 第二个 next 方法带有参数2,这个参数可以传入 Generator 函数,作为上个阶段异步任务的返回结果,被函数体内的变量 y 接收。因此,这一步的 value 属性,返回的就是2(变量 y 的值)。
🌵🌵然后是拓展上面的🌰例子(明确y被赋值的时机):
var y;
function* gen(x){
y = yield x + 2;
return y;
}
var g = gen(1);
g.next(1) // { value: 3, done: false }
console.log(y)//undefined
g.next(11)
console.log(y) // 11
- 第一次next传参数和不传参数都没用,只是启动了运行,一旦调用
next,函数体就开始执行,一旦遇到yield就返回执行结果,暂停执行 - 第二次
next的参数会作为第一次yield的结果传递给函数体,以此类推,所以第一次next调用的参数没用
再举个🌰例子
function* add() {
console.log('start');
// x 可真的不是yield '2'的返回值,它是next()调用 恢复当前yield()执行传入的实参
let x = yield '2';
console.log('one:'+x);
let y = yield '3';
console.log('two:'+y);
return x+y;
}
const fn = add();
console.log(fn.next()); //{value:'2',done:false}
console.log(fn.next(20)); //{value:'3',done:false}
console.log(fn.next(30)); //{value:50,done:true}
🌵小结:
- 第一次调用next,传入的参数是无效的,因为此时生成器内部还没有运行接受参数的一步,即yield操作还没有进行过,第一个值并没有产生,所以是无法接收next的参数的
🌵使用场景:
🤔什么是 for…of 循环?
for...of 语句创建一个循环来迭代可迭代的对象。 在 ES6 中引入的 for...of 循环,以替代 for...in 和 forEach() ,并支持新的迭代协议。for...of 允许你遍历 Arrays(数组), Strings(字符串), Maps(映射), Sets(集合)等可迭代的数据结构等。
let obj = {
x:10,
y:20
}
for(objItem of obj){
console.log(objItem)
}
// Uncaught TypeError: obj is not iterable
//obj对象是一个不可迭代的对象,或者说它没有迭代器。
// 使用场景1:为不具备Interator接口的对象提供了遍历操作
const obj = {
name:'小马哥',
age:18
}
function* objectEntries(obj) {
// 获取对象的所有的key保存到数组 [name,age]
const propKeys = Object.keys(obj);
for(const propkey of propKeys){
yield [propkey,obj[propkey]]
}
}
obj[Symbol.iterator] = objectEntries;
// console.log(obj);
// 来看看使用for of来遍历迭代器后会得到什么?
for(let item of objectEntries(obj)){
console.log(item);
}
// ["name", "小马哥"]
// ["age", 18]
// 这里面相当于直接对item进行了es6解构赋值
for(let [key,value] of objectEntries(obj)){
console.log(`${key}:${value}`);
}
// name:小马哥
// age:18