实现一个LazyMan,能够按照如下方式调用:面试
LazyMan(“Hank”)输出:bash
Hi! This is Hank!markdown
LazyMan(“Hank”).sleep(10).eat(“dinner”)输出this
Hi! This is Hank!spa
//等待10秒..prototype
Wake up after 10code
Eat dinner~orm
LazyMan(“Hank”).eat(“dinner”).eat(“supper”)输出it
Hi This is Hank!io
Eat dinner~
Eat supper~
LazyMan(“Hank”).sleepFirst(5).eat(“supper”)输出
//等待5秒
Wake up after 5
Hi This is Hank!
Eat supper
以此类推。
尝试着作了一下,发现没有想象的简单,虽然作出来了,可是若是是在面试的状况下就压力山大了,大厂就是不同!
如下是代码,注释省略
function LazyMan(obj) { if (obj instanceof LazyMan) { return obj } if (!(this instanceof LazyMan)) { return new LazyMan(obj) } this.name = obj this.cbManager = [] this.timer = null this.say() } LazyMan.prototype.addCb = function (isAsync, cb) { if (this.timer) { this.cbManager.push({ isAsync, cb }) } else { cb() } } LazyMan.prototype.sleep = function (time) { this.addCb(true, () => setTimeout(() => this.handleCb(), time * 1000)) return this } LazyMan.prototype.eat = function (food) { this.addCb(false, () => console.log(food)) return this } LazyMan.prototype.sleepFirst = function (time) { this.timer && clearTimeout(this.timer) this.timer = setTimeout(() => this.say(), time * 1000) return this } LazyMan.prototype.say = function () { this.timer = setTimeout(() => { console.log(this.name) this.handleCb() }, 0) } LazyMan.prototype.handleCb = function () { const next = this.cbManager.shift() if (next) { next.cb() !next.isAsync && this.handleCb() } } // LazyMan('Hank') // LazyMan('Hank').eat('dinner').eat('supper') // LazyMan('hank').sleep(5).eat('dinner') // LazyMan('hank').sleep(5).eat('dinner').sleep(5).eat('supper') LazyMan('Hank').sleepFirst(5).eat('supper').sleep(5).eat('dinner') 复制代码
三个月后再看这道题,总以为上面这个实现方式不太优雅,所以换个思路实现,如下是代码:
function LazyMan(name) { if (!(this instanceof LazyMan)) { return new LazyMan(name) } const cb = next => { console.log(`hi, this is ${name}`) next() } this.cbs = [cb] setTimeout(() => this.next(), 0) } LazyMan.prototype.sleep = function (time) { const cb = next => setTimeout(() => next(), time * 1000) this.cbs.push(cb) return this } LazyMan.prototype.sleepFirst = function (time) { const cb = next => setTimeout(() => next(), time * 1000) this.cbs.unshift(cb) return this } LazyMan.prototype.eat = function (food) { const cb = next => { console.log(`eat ${food}`) next() } this.cbs.push(cb) return this } LazyMan.prototype.next = function () { if (this.cbs.length <= 0) return const first = this.cbs.shift() first(this.next.bind(this)) } 复制代码
不知道有没有更优雅的方法