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 对象上的方法,如 next,return,throw等方法
如果把 generator 函数当作普通的构造函数,则并不会生效,
因为它返回的总是遍历器对象,而不是 this 对象。
generator 函数也不能跟new 命令一起起用,否则会报错。
可以通过
call、apply、bind等方法更改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())
来源:oschina
链接:https://my.oschina.net/u/4162046/blog/3220730