题目:实现一个方法,可以按顺序打印出需要的文字
function machine (name) {
}
machine('ygy').execute()
// start ygy (输出)
machine('ygy').do1('eat').execute();
// start ygy (输出)
// ygy eat (输出)
machine('ygy').wait(1).do1('eat').execute();
// start ygy (输出)
// wait 1s(等待1s)
// ygy eat (输出)
machine('ygy').waitFirst(5).do1('eat').execute();
// wait 5s (等待5s)
// start ygy (输出)
// ygy eat (输出)
这是一个典型的链式调用,如果不考虑异步的任务的话,只需要在每个方法后面返回this就可以实现链式调用。
function machine (name) {
this.name = name
this.do1 = function (action) {
console.log(`${this.name} ${action}`)
return this
}
this.execute = function () {
console.log(`start ${this.name}`)
return this
}
return this
}
// 这样可以实现链式调用但是顺序不对
machine('ygy').do1('eat').execute();
// ygy eat (输出)
// start ygy (输出)
观察一下别的输出要求,每个execute都是最后调用,但是需要最先打印,我想到的解决方法是用一个变量存储一下是否已经打印了 start
function machine (name) {
this.name = name
this.started = false
this.doStart = function () {
if (!this.started) {
console.log(`start ${this.name}`)
this.started = true
}
}
this.do1 = function (action) {
this.doStart()
console.log(`${this.name} ${action}`)
return this
}
this.execute = function () {
this.doStart()
return this
}
return this
}
// 这样打印的顺序就是对的了
machine('ygy').do1('eat').execute();
// start ygy (输出)
// ygy eat (输出)
接下来就是异步的任务,它需要我们自己实现一个事件栈,在任务执行完之后再执行下一个任务。
function machine (name) {
this.name = name
this.started = false
this.actions = []
this.next = function () {
this.doStart()
// 先进先出
let fn = this.actions.shift()
fn && fn()
}
this.doStart = function () {
if (!this.started) {
console.log(`start ${this.name}`)
this.started = true
}
}
this.do1 = function (action) {
// 讲要执行的函数推入事件栈,并且在函数中调用next
this.actions.push(() => {
console.log(`${this.name} ${action}`)
this.next()
})
return this
}
this.wait = function (sec) {
// 讲要执行的函数推入事件栈,并且在函数中调用next
this.actions.push(() => {
setTimeout(() => {
console.log(`wait ${sec}s`)
this.next()
}, sec * 1000);
})
return this
}
this.execute = function () {
this.next()
}
return this
}
machine('ygy').wait(1).do1('eat').execute();
// start ygy (输出)
// wait 1s(等待1s)
// ygy eat (输出)
waitFirst 需要先等待,等待完成后再开始执行,我的想法是用started 这个变量控制打印开始的时间。
function machine (name) {
...
this.waitFirst = function (sec) {
this.started = true
this.actions.push(() => {
setTimeout(() => {
console.log(`wait ${sec}s`)
this.started = false
this.next()
}, sec * 1000);
})
return this
}
this.execute = function () {
this.next()
}
return this
}
machine('ygy').waitFirst(5).do1('eat').execute();
// wait 5s (等待5s)
// start ygy (输出)
// ygy eat (输出)
完整代码
function machine (name) {
this.name = name
this.started = false
this.actions = []
this.next = function () {
this.doStart()
// 先进先出
let fn = this.actions.shift()
fn && fn()
}
this.doStart = function () {
if (!this.started) {
console.log(`start ${this.name}`)
this.started = true
}
}
this.do1 = function (action) {
this.actions.push(() => {
console.log(`${this.name} ${action}`)
this.next()
})
return this
}
this.wait = function (sec) {
this.actions.push(() => {
setTimeout(() => {
console.log(`wait ${sec}s`)
this.next()
}, sec * 1000);
})
return this
}
this.waitFirst = function (sec) {
this.started = true
this.actions.push(() => {
setTimeout(() => {
console.log(`wait ${sec}s`)
this.started = false
this.next()
}, sec * 1000);
})
return this
}
this.execute = function () {
this.next()
}
return this
}
由于在面试中过于紧张导致这道题并没有做出来😅,有没有小伙伴对链式调用感兴趣可以讨论一下