generator函数yield

冷暖自知 提交于 2020-04-07 11:08:07

Generator 函数

yield*表达式

如果在 generator 函数内部调用另一个 generator 函数,默认情况下是没有效果的。

yield* 后面的 Generator 函数(没有 return 语句时)等同于在 generator 函数内部部署 for...of 循环

        // 定义generator函数
        function* ickt(){
            yield 1;
            yield 2;
        }
        function* demo(){
            yield "ljh";
            yield "ljh1";
            // 直接执行 ickt
            // ickt();//  无效
            // yield ickt();// ['ljh','ljh','ickt']
            //返回状态机中的状态
            // let i= ickt();
            // for(let item of i){
            //     console.log(item)
            //     yield item;
            // }
            // yield*表达式
            yield* ickt();
            yield "12";
        }
        let d = demo();
        console.log([...d])

yield* 后面跟着 个数组,由于数组原生支持遍历器,因此就会遍历数组成员 任何数据结构只要有 Iterator 接口,就可以被 yield* 遍历

        // 定义generator函数
        function* ickt(){
            yield 1;
            yield 2;
            // 将函数内部的数据 传递给yield*表达式或者其他的变量 内部向外部传递数据
            // next 方法 外部向内部传递数据
            return "ljh"
        }
        function* demo(){
            yield "ljh";
            yield "ljh1";
            // 直接执行 ickt
            // ickt();//  无效
            // yield ickt();// ['ljh','ljh','ickt']
            //返回状态机中的状态
            // let i= ickt();
            // for(let item of i){
            //     console.log(item)
            //     yield item;
            // }
            // yield*表达式
            // yield* ickt();
            // yield "12";
            // yield* 只要实现便利器接口的数据都可以
            // yield* [1,2,3];
            // yield* arguments; //获取传递的参数
            // yield* "lijh";
            // yield* 不会遍历return的数据
            let retsult = yield* ickt();
            console.log(retsult)

        }
        let d = demo(1,3,4,5,6);
        console.log([...d])

如果被代理的 generator 函数有 return 语句,那么便可以向代理它的 generator 函数返回数据。

        //数组降维、
        let arr = ['a', ['b', ['c', ['d', 'e', ['f'], 'g'], ['h']]], 'i'];
        // console.log(arr.flat(5))    
        // 第一种方式
        // function dealArray(arr){
        //     return arr.map(item=>{
        //         if(Array.isArray(item)){
        //             return dealArray(item.flat())
        //         }
        //         return item
        //     }).flat()
        // }
        // console.log(dealArray(arr))
        //第二种方式 
        //  function dealArray(arr){
        //     return arr.map(item=>{
        //         if(Array.isArray(item)){
        //             return dealArray(item.flat())
        //         }
        //         return item
        //     }).flat()
        // }  
        // function* deal(){
        //     for(let item of dealArray(arr)){
        //         yield item
        //     }
        // } 
        // console.log([...deal()])
        //第三种方式
        function* deaaArr(arr){
            //遍历成员
            for(let item of arr){
                //判断数组
                if(Array.isArray(item)){
                    yield* deaaArr(item)
                }else{
                    yield item 
                }
            }

        }
        console.log([...deaaArr(arr)])

二叉树

//                 'a'
//         'b'             'c'
//     'd'     'e'     'f'     'g'
//   'h' 'i'        'j'   'k'
// 定义数组
let arr = [[[['h'], 'd', ['i']], 'b', ['e']], 'a', [[['j'], 'f', ['k']], 'c', ['g']]]
// 定义树类
function Tree(left, center, right) {
    // 存储
    // this.left = left;
    // this.center = center;
    // this.right = right;
    // 简化
    Object.assign(this, { left, center, right })
}
// 属性没有名字
// function Tree(...arg) {
//     Object.assign(this, { ...arg })
// }
// 测试
// console.log(new Tree('a', 'b', 'c'));
// 转化方法
function deal(arr) {
    // 只有叶子节点
    if (arr.length === 1) {
        return new Tree(null, arr[0], null)
    }
    return new Tree(deal(arr[0]), arr[1], deal(arr[2]))
}
let tree = deal(arr);
// 将节点变成状态
function* ickt(t) {
    t.left && (yield* ickt(t.left));
    yield t.center;
    t.right && (yield* ickt(t.right));
}
// console.log([...ickt(tree)])
let demo = ickt(tree);
console.log(demo.next())
console.log(demo.next())
console.log(demo.next())
console.log(demo.next())
console.log(demo.next())

yield* 命令可以很方便地取出嵌套数组的所有成员

this指向

generator 函数总是返回一个遍历器对象。 ES6 规定这个遍历器是 generator 函数的实例 ,它也继承了 generator 函数的 prototype 对象上的方法,如 nextreturnthrow等方法

如果把 generator 函数当作普通的构造函数,则并不会生效, 因为它返回的总是遍历器对象,而不是 this 对象。

generator 函数也不能跟new 命令一起起用,否则会报错。

可以通过 callapplybind 等方法更改 generator 函数运行的上下文对象,此时 this 指向该对象

我们也可以将 generator 函数作为对象的属性方法,在对象字面量中,可以省略 function 关键字,直接在函数名称前面加 * 号。

// 定义generator函数
function* demo() {
    // console.log(this, 111)
    // 不能通过this存储数据
    this.color = 'red';
    yield 1;
    // 分阶段拓展数据
    this.width = 10;
    yield 2;
    this.height = 20;
}
// 原型方法
// demo.prototype.num = 10;
Object.assign(demo.prototype, {
    num: 20,
    msg: 'hello',
    getMsg() {
        console.log(this.msg)
    }
})
// let d = demo()
// 不能使用new关键字
// let d = new demo()
// // 可以更改上下文环境
// let obj = { title: 'ickt' };
// // let d = demo.call(obj);
// // 让demo在原型对象上运行,此时this指向原型对象,数据被添加到原型对象上,
// let d = demo.call(demo.prototype)
// // 执行next方法,才能启动demo
// d.next();

// console.log(d, obj)
// console.log(d.color)
// console.log(d.title)
// d.getMsg()

// 普通函数运行完毕,没有结果,无法获取原型上的数据
// function ickt() {}
// ickt.prototype.num = 20;
// console.log(ickt());

封装generator函数类

        // 定义generator函数
        function* demo() {
            // console.log(this, 111)
            // 不能通过this存储数据
            this.color = 'red';
            yield 1;
            // 分阶段拓展数据
            this.width = 10;
            yield 2;
            this.height = 20;
        }
        // 原型方法
        // demo.prototype.num = 10;
        Object.assign(demo.prototype, {
            num: 20,
            msg: 'hello',
            getMsg() {
                console.log(this.msg)
            }
        })
        function dealDemo(fn){
            //安全检测
            if (Object.prototype.toString.call(fn) === "[object GeneratorFunction]") {
                // 在generator函数中,通过this存储数据
                return fn.call(fn.prototype)
            }
            throw new Error('必须传递generator函数')
        }
        let dd = new dealDemo(demo)
        console.log(dd.next())
        console.log(dd.color)
        console.log(dd.width)

对象添加generator函数

let obj = {
    // 普通函数可以简写,generator函数也可以简写
    // test: function* () {
    //     yield 1;
    // }
    * test() {
        yield 5;
    }
}
console.log(obj.test().next())
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!