链式调用
如果我们经常使用 jQuery ,我们写代码就会有时候这样写,这种就是我们最常用的链式调用
$(ele).show().find(child).hide()
实现这种链式调用的本质是,方法体内返回对象实例自身 this,让下一个对象的属性能够继续获取该对象的其他属性从而一直驱动着程序
varobj={a: 1,func: function(){this.a+=1;returnthis}}obj.func().func();console.log(Obj.a);// 3但是如果链式调用中出现异步的函数的时候,我们就要用一个数组来进行集中式管理,类似一个队列的顺序规范,下面的 Queue 类就是一个重要的例子,关键点在于数组this.task = []还有next()的出队列的过程,让每一个函数在链式调用的时候进去数组this.task = []里面缓存起来,然后用用next()不断触发下一个函数的执行,这里面涉及数组的几个常用的方法,比如要置顶到队列前排,类似插队的草最就用unshift(),平时的按正常顺序进队列最后排的就用push(),而从头部出队列执行就用shift()
| 方法 | 作用 |
|---|
shift() | 删除并返回数组的第一个元素 |
unshift() | 向数组的开头添加一个或更多元素,并返回新的长度 |
push() | 向数组的末尾添加一个或更多元素,并返回新的长度 |
classQueue{constructor(){this.task=[];setTimeout(()=>{this.next();},0)}next(){// 先进先出 队列的过程letfn=this.task.shift();// 删除并返回数组的第一个元素fn&&fn();}// 置顶执行// 任务队列头部添加,然后执行头部first(callback,timer){letfn=()=>{setTimeout(()=>{callback();this.next();},timer*1000)}this.task.unshift(fn);// 向数组的开头添加一个或更多元素,并返回新的长度returnthis;}// 延时执行// 任务队列尾部添加,然后执行头部time(callback,timer){letfn=()=>{setTimeout(()=>{callback()this.next();},timer*1000)}this.task.push(fn);// 向数组的末尾添加一个或更多元素,并返回新的长度returnthis;}// 顺序执行// 和延时执行其实一样,只是延时会卡在哪里等待过完再往下走// 任务队列尾部添加,然后执行头部work(callback){letfn=()=>{callback();this.next();}this.task.push(fn);returnthis;}}newQueue().first(()=>{console.log(0)},2).first(()=>{console.log(1)},2).work(()=>{console.log(2)}).time(()=>{console.log(3)},1)// 1 0 2 3// 两个置顶先执行,谁后置顶谁执行生成器函数
function* 这种声明方式(function关键字后跟一个星号)会定义一个生成器函数(generator function),它返回一个 Generator 对象
function*fn(){console.log(1);//暂停!yield;//调用next方法继续执行console.log(2);}variter=fn();iter.next();//1iter.next();//2生成器函数在执行时能暂停,后面又能从暂停处继续执行,每 next 一次就执行每个 yield 间隔之间的代码,本质就是动态移动指针
- 函数生成器特点是函数名前面有一个
* - 通过调用函数生成一个控制器
- 调用
next()方法开始执行函数 - 遇到
yield函数将暂停 - 再次调用
next()继续执行函数
调用next()方法时,如果传入了参数,那么这个参数会作为上一条执行的yield语句的返回
function*gen(){yield10;y=yield'foo';yieldy;}vargen_obj=gen();console.log(gen_obj.next());// 执行 yield 10,返回 10console.log(gen_obj.next());// 执行 yield 'foo',返回 'foo'console.log(gen_obj.next(10));// 将 10 赋给上一条 yield 'foo' 的左值,即执行 y=10,返回 10console.log(gen_obj.next());// 执行完毕,value 为 undefined,done 为 true传递参数
function*createIterator(){letfirst=yield1;letsecond=yieldfirst+2;// 4 + 2 // first =4 是next(4)将参数赋给上一条的yieldsecond+3;// 5 + 3}letiterator=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 }"注意显式返回和生成器函数不能当构造器使用
function*yieldAndReturn(){yield"Y";return"R";//显式返回处,可以观察到 done 也立即变为了 trueyield"unreachable";// 不会被执行了}vargen=yieldAndReturn()console.log(gen.next());// { value: "Y", done: false }console.log(gen.next());// { value: "R", done: true }console.log(gen.next());// { value: undefined, done: true }function*f(){}varobj=newf;// throws "TypeError: f is not a constructor"
链式调用
如果我们经常使用 jQuery ,我们写代码就会有时候这样写,这种就是我们最常用的链式调用
实现这种链式调用的本质是,方法体内返回对象实例自身 this,让下一个对象的属性能够继续获取该对象的其他属性从而一直驱动着程序
但是如果链式调用中出现异步的函数的时候,我们就要用一个数组来进行集中式管理,类似一个队列的顺序规范,下面的 Queue 类就是一个重要的例子,关键点在于数组
this.task = []还有next()的出队列的过程,让每一个函数在链式调用的时候进去数组this.task = []里面缓存起来,然后用用next()不断触发下一个函数的执行,这里面涉及数组的几个常用的方法,比如要置顶到队列前排,类似插队的草最就用unshift(),平时的按正常顺序进队列最后排的就用push(),而从头部出队列执行就用shift()shift()unshift()push()生成器函数
function*这种声明方式(function关键字后跟一个星号)会定义一个生成器函数(generator function),它返回一个 Generator 对象生成器函数在执行时能暂停,后面又能从暂停处继续执行,每 next 一次就执行每个 yield 间隔之间的代码,本质就是动态移动指针
*next()方法开始执行函数yield函数将暂停next()继续执行函数调用
next()方法时,如果传入了参数,那么这个参数会作为上一条执行的yield语句的返回传递参数
注意显式返回和生成器函数不能当构造器使用