生成器Generator

生成器(Generator)

​ 生成器是一种特殊的函数类型。生成器能生成一组值的序列,生成每个值之前都需要迭代器(Iterator)向生成器发送一次next请求,当生成器接收到一次请求并生成一个当前值后,它并不会向像普通函数那样停止执行,而是会非阻塞地挂起执行进行等待,当接收到下一个请求时,它会从上次离开的位置恢复执行。

​ 当调用迭代器的next方法向生成器请求新值时会返回一个携带生成值的对象,该对象还包含着一个done属性,用于标记生成器是否完成迭代。

//定义生成器函数
function* AnimalsGenerator(){
    yield "Tiger";
    yield "Panda";
}
const AnimalsIterator = AnimalsGenerator();// 调用生成器函数得到迭代器
// 调用next方法向生成器获取新值
const result1 = AnimalsIterator.next();
const result2 = AnimalsIterator.next();
const result3 = AnimalsIterator.next();

console.log(result1, result2);// {value: "Tiger", done: false} {value: "Panda", done:false}
console.log(result3);//{value: undefined, done: true}

利用 for-of 循环进行迭代

//定义生成器函数
function* AnimalsGenerator(){
    yield "Tiger";
    yield "Panda";
}
//利用for-of循环进行迭代,获取所有生成值
for(let item of AnimalsGenerator()){
    console.log(item); //Tiger Panda
}

实现

const AnimalsIterator = AnimalsGenerator();// 调用生成器函数得到迭代器
let item;
//调用next方法获取item对象,仅当item的done属性为false时执行
while( !(item = AnimalsIterator.next()).done ){
    //仅当item的属性不为undefined时,输出value
    if(item.value !== undefined)
        console.log(item.value);
}

生成器执行的委托

​ 生成器在生成的过程中可以将执行权委托给另一个生成器,这时生成器会跳转到另一个生成器上执行,直到委托生成器执行完成后,才回到原来的序列中继续执行。

//定义生成器函数
function* AnimalsGenerator(){
    yield "Tiger";
    yield* AgentGenerator();
    yield "Panda";
}
//定义委托生成器
function* AgentGenerator(){
    yield "agent-Lion";
    yield "agent-Monkey";
}
//对生成器进行迭代
for(var item of AnimalsGenerator()){
    console.log(item); //Tiger agent-Lion agent-Monkey Panda
}

生成器的应用

​ 1、实现DOM的深度遍历

function* DomDepTraversal(element){
    yield element;
    element = element.firstElementChild; //生成elemnet的子节点
    while(element){
        yield* DomDepTraversal(element); //递归调用返回当前element
        element = element.nextElementSibling; //遍历完所有子节点后,生成element的兄弟节点
    }
}

for(let item of DomDepTraversal(subTree)){
    console.log(item);
}
<--------!DOM结构---------->
<div id="subTree">
    <ul>
        <li></li>
	<li></li>
    </ul>
    <div>
         <ul></ul>
    </div>
</div>

next指向图

调用栈

​ 在第一次接收请求时,生成器直接在第一层返回element。

​ 处理第二次请求时,生成器执行挂起前的下一句,将element的第一个子节点ul赋值给element;element不为空,进入while循环,匹配到yield* 进入第二层生成器,在第二层返回element(ul)。

​ 处理第三次请求时,回到第二层生成器,得到element的第一个子节点li;element不为空,进入while循环,匹配到yield* 进入第三层生成器,在第三层返回element(li)。

​ 处理第四次请求时,回到第三层生成器,element子节点为空,不执行while循环;跳转回第二层的while循环中,得到element的下一兄弟节点li,element不为空,继续执行while循环,匹配到yield* 进入第三层生成器在第三层返回element(li)。

​ 处理第五次请求时,回到第三层生成器,element子节点为空,不执行while循环;跳转回第二层的while循环中,element的下一兄弟节点为空,结束while循环;跳转回第一层的while循环中,得到element的下一兄弟节点div,element不为空,继续执行while循环,匹配到yield* 进入第二层生成器在第二层返回element(div)。

​ 处理第六次请求时,回到第二层生成器,得到element的第一个子节点ul;element不为空,进入while循环,匹配到yield* 进入第三层生成器,在第三层返回element(ul)。

​ 处理第七次请求时,回到第三层生成器,element的子节点为空,不执行while循环;跳转回第二层的while循环中,element的下一兄弟节点为空,结束while循环;跳转回第一层的while循环中,element下一兄弟节点为空,结束while循环;生成器函数执行完毕。

生成器的生命周期

image

1、从调用生成器函数得到迭代器,生成器处于挂起开始状态,等待迭代器发送第一个next请求。

2、生成器接收到迭代器发送的第一个next请求后,生成器由挂起开始状态转换为执行状态,向下执行生成器函数。

3、当生成器函数执行到yield语句时,生成器由执行状态转换为挂起让渡状态,中止向下执行函数并返回一个携带生成值的对象,等待迭代器发送next请求。

4、当生成器接收到迭代器发送的next请求后,生成器由挂起让渡状态转换为执行状态,函数回到上次挂起时的语句,继续想想执行生成器函数,直到执行到yield语句,生成器再回到挂起让渡状态。

5、当生成器接收到迭代器发送的next请求后,生成器函数执行完毕,生成器由执行状态转到完成状态。

posted @ 2021-06-17 17:12  yiugamcheung  阅读(147)  评论(0)    收藏  举报