题目:如何实现一个LazyMan?
实现一个LazyMan,可以按照以下方式调用:
LazyMan(“Hank”)输出:
Hi! This is Hank!
LazyMan(“Hank”).sleep(10).eat(“dinner”)输出
Hi! This is Hank!
//等待10秒..
Wake up after 10
Eat dinner~
LazyMan(“Hank”).eat(“dinner”).eat(“supper”)输出
Hi This is Hank!
Eat dinner~
Eat supper~
LazyMan(“Hank”).sleepFirst(5).eat(“supper”)输出
//等待5秒
Wake up after 5
Hi This is Hank!
Eat supper
以此类推。
可以借鉴jQuery的实现方式。要想实现链式调用,可以声明一个函数,这个函数返回一个对象,这个对象里就拥有这些方法,而且每个方法都要返回此对象,才能实现链式调用。也可以声明一个构造函数,new 这个构造函数 会生成一个实例,这些方法就挂在实例的原型上,而且这个方法也都返回当前实例。
还有一个关键点就是考察JS的流程控制。如何才能实现任务的顺序执行。而且遇到sleep还要休息几秒钟,之后再执行它后边的函数。通过使用任务队列和next函数来实现。
next函数里是为了执行下一个任务的。具体:从任务队列里取出最前边的那个函数,执行它。
每次 .eat() 之类的,这个eat方法里就定义一个函数,函数里先做它自己做的事,做完以后再去调用next。定义完以后,把这个函数push进任务队列,等待被调用。然后返回当前对象。
这些方法都是按照这种套路来写。先定义一个函数fn,fn里边先做自己的事,然后next()将棒交给下一个任务。然后把fn push进任务队列。最后一定要返回对象,才能链式调用
写的时候要注意this的指向,正确使用普通函数和箭头函数。
- 下边是用构造函数的方法:
构造函数要用new来调用。但是这个题目里是LazyMan(“Hank”)来开始,没有new。所以我们可以让LazyMan函数返回new _LazyMan()这个实例,eat这些方法里也返回这个实例。
function _LazyMan(name){
this.task=[]
const fn=()=>{
console.log(`Hi! This is ${name}!`)
this.next()
}
this.task.push(fn)
setTimeout(()=>{
this.next()
},0)
}
_LazyMan.prototype.next=function(){
let f=this.task.shift()
f && f()
}
_LazyMan.prototype.eat=function(name){
const fn=()=>{
console.log(`Eat ${name}~`)
this.next()
} //eat里的this是对象实例,为了让fn里的this也是对象实例,fn要用箭头函数
this.task.push(fn)
return this
}
_LazyMan.prototype.sleep=function(time){
const fn=()=>{
setTimeout(()=>{
console.log(`Wake up after ${time}`)
this.next()
},time*1000)
}
this.task.push(fn)
return this
}
_LazyMan.prototype.sleepFirst=function(time){
const fn=()=>{
setTimeout(()=>{
console.log(`Wake up after ${time}`)
this.next()
},time*1000)
}
this.task.unshift(fn) //先睡,再干别的。可以把fn放在队列最开头,而不是放末尾
return this
}
function LazyMan(name){
return new _LazyMan(name)
}
LazyMan('Hank').eat('dinner').eat('supper')
//LazyMan('Hank').sleep(3).eat('dinner')
//LazyMan('Hank').sleepFirst(5).eat('supper')
- 另一个题目,用普通函数实现。返回的对象是函数里定义的一个普通对象。
实现一个chain, eat函数打印eat,work函数打印work,sleep函数休息
chain().eat().sleep(5).work().eat().work().sleep(10)
function chain(){
let tasks=[]
const fn=()=>{
obj.next()
}
tasks.push(fn)
setTimeout(()=>{
obj.next()
},0)
let obj= {
next(){
const f=tasks.shift()
f && f()
},
eat(){
const fn=()=>{
console.log('eat')
this.next()
} //eat里的this是obj,因为obj.eat()。要想让fn里的this也是obj,fn就要是箭头函数
tasks.push(fn)
return obj
},
work(){
const fn=()=>{
console.log('work')
this.next()
}
tasks.push(fn)
return obj
},
sleep(time){
const fn=()=>{
setTimeout(()=>{
this.next()
},time*1000)
}
tasks.push(fn)
return obj
}
}
return obj
}