一道有意思的微信前端面试题

1,006 阅读1分钟

实现一个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

以此类推。


尝试着做了一下,发现没有想象的简单,虽然做出来了,但是如果是在面试的情况下就压力山大了,大厂就是不一样!

以下是代码,注释省略

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))
}

不知道有没有更优雅的方法