javascript - 一个面试题,有啥想法么?
本文介绍了javascript - 一个面试题,有啥想法么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
问 题
实现函数LazyMan,使得:
LazyMan('Hank'); 输出
Hi Hank!
LazyMan('Hank').eat('dinner');输出
Hi Hank!
Eat dinner!
LazyMan('Hank').sleep(5).eat('dinner'); 输出:
Hi Hank!
//等待五秒
Eat dinner!
LazyMan('Hank').sleepFirst(5).eat('dinner');输出:
//等待五秒
Hi Hank!
Eat dinner!
解决方案
2017-4-12 更新,美化下输出结果。
function LazyMan(nick){
var obj = {
task : {
list : [],
add : function(fun, timer){
timer = timer || 0;
this.task.list.push({
fun : fun,
timer : timer
});
return this;
},
run : function(){
if( this.task.list.length > 0 ){
setTimeout( (function(){
this.task.list.shift().fun.call(this);
}).bind(this), this.task.list[0].timer );
}else{
this.echo("[Task]", "==========Stop==========");
}
}
},
echo : function( str , str2 ){
var message = {
isLog : !!str.match(/^\[[\s\S]*\]$/),
style : [
'color:#090;font-size:1.2em;font-weight:800;',
'color:#CCC;font-size:0.5em;font-style:italic;',
],
text : str + str2
};
if( 'table' in console ){
//
console.log('%c%s', message.style[+message.isLog], message.text );
}else{
!message.isLog && console.log(message.text );
}
delete message;
return this;
},
hello : function( nick ){
return this.task.add.call(this, function(){
this.echo('Hi', nick);
this.task.run.call(this);
});
},
eat : function( eat ){
return this.task.add.call(this, function(){
this.echo('Eat', eat);
this.task.run.call(this);
});
},
sleep : function( timer ){
return this.task.add.call(this, function(){
this.echo("[Timer( sleep )]", timer);
this.task.run.call(this);
}, timer * 1000);
},
sleepFirst : function( timer ){
var fun = this.task.list[0].fun;
this.task.list[0].fun = function(){
setTimeout((function(){
this.echo("[Timer( sleepFirst) ]", timer);
fun.call(this);
}).bind(this), timer * 1000);
};
return this;
}
};
obj.echo("[Task]", "==========Start==========").hello(nick).task.run.call(obj);
return obj;
};
LazyMan("A").sleepFirst(1).eat("abc").sleep(4).sleep(5).eat("A").eat("B").eat("C")
======================
2017-3-22 代码再次更新,受一道面试题的启发。重新优化了代码(不等待时,setTimeout的间隔时间为0):
function LazyMan(nick){
var obj = {
task : {
list : [],
add : function(fun, timer){
timer = timer || 0;
this.task.list.push({
fun : fun,
timer : timer
});
return this;
},
run : function(){
if( this.task.list.length > 0 ){
setTimeout( (function(){
this.task.list.shift().fun.call(this);
}).bind(this), this.task.list[0].timer );
}else{
this.echo("[Task]", "==========Stop==========");
}
}
},
echo : function( str , str2 ){
console.log( str + ' ' + str2 );
return this;
},
hello : function( nick ){
return this.task.add.call(this, function(){
this.echo('Hi', nick);
this.task.run.call(this);
});
},
eat : function( eat ){
return this.task.add.call(this, function(){
this.echo('Eat', eat);
this.task.run.call(this);
});
},
sleep : function( timer ){
return this.task.add.call(this, function(){
this.echo("[Timer( sleep )]", timer);
this.task.run.call(this);
}, timer * 1000);
},
sleepFirst : function( timer ){
var fun = this.task.list[0].fun;
this.task.list[0].fun = function(){
setTimeout((function(){
this.echo("[Timer( sleepFirst) ]", timer);
fun.call(this);
}).bind(this), timer * 1000);
};
return this;
}
};
obj.echo("[Task]", "==========Start==========").hello(nick).task.run.call(obj);
return obj;
};
LazyMan("A").sleepFirst(1).eat("abc").sleep(4).sleep(5).eat("A").eat("B").eat("C")
得到启发的代码如下:
var a = true;
setTimeout(function(){
a = false;
}, 0);
while( a == true ){}
alert('x'); //alert永远不会执行。JS作为一个单线程语言,只有处理完队列中的任务后,才会去去调用setTimeout的队列。
以下是原答案:
重新来答一遍,这次是认真的,使用了任务队列,同样只使用了一个函数,没用使用Promise,没有使用 timer累加的方法,保证最多只有一个计时器在运行,同时能获取任务开始和最终结束时间。
核心部分是一个 setTimeout 和 一个 任务队列(数组)。
因为使用了队列流程,处理完一个再处理下一个,所以支持多次输出,多次等待,而程序不会乱掉。 LazyMan("A").sleepFirst(1).eat("abc").sleep(4).sleep(5).eat("A").eat("B").eat("C")
function LazyMan(nick){
var obj = {
task : {
list : [],
add : function(timer, fun){
timer = timer || 16;
this.task.list.push({
fun : fun,
timer : timer
});
return this;
},
run : function(){
if( this.task.list.length > 0 ){
setTimeout( (function(){
this.task.list.shift().fun.call(this);
}).bind(this), this.task.list[0].timer );
}else{
this.echo("[Task]", "==========Stop==========");
}
}
},
echo : function( str , str2 ){
console.log( str + ' ' + str2 );
return this;
},
hello : function( nick ){
return this.task.add.call(this, 16, function(){
this.echo('Hi', nick);
this.task.run.call(this);
});
},
eat : function( eat ){
return this.task.add.call(this, 16, function(){
this.echo('Eat', eat);
this.task.run.call(this);
});
},
sleep : function( timer ){
return this.task.add.call(this, timer * 1000, function(){
this.echo("[Timer( sleep )]", timer);
this.task.run.call(this);
});
},
sleepFirst : function( timer ){
var fun = this.task.list[0].fun;
this.task.list[0].fun = function(){
setTimeout((function(){
this.echo("[Timer( sleepFirst) ]", timer);
fun.call(this);
}).bind(this), timer * 1000);
};
return this;
}
};
obj.echo("[Task]", "==========Start==========").hello(nick).task.run.call(obj);
return obj;
};
测试下结果:
LazyMan('Hank');
/*
[Task] ==========Start==========
Hi Hank
[Task] ==========Stop==========
*/
LazyMan('Hank').eat('dinner');
/*
[Task] ==========Start==========
Hi Hank
Eat dinner
[Task] ==========Stop==========
*/
LazyMan('Hank').sleep(5).eat('dinner');
/*
[Task] ==========Start==========
Hi Hank
[Timer( sleep )] 5
Eat dinner
[Task] ==========Stop==========
*/
LazyMan('Hank').sleepFirst(5).eat('dinner');
/*
[Task] ==========Start==========
[Timer( sleepFirst) ] 5
Hi Hank
Eat dinner
[Task] ==========Stop==========
*/
LazyMan('来搞笑的小吃货').sleepFirst(1).eat('西瓜').eat('甜瓜').eat('哈密瓜').sleep(2).eat('苹果').eat('橘子').eat('香蕉').sleep(3).sleep(4).eat('撑死了');
/*
[Task] ==========Start==========
[Timer( sleepFirst) ] 1
Hi 来搞笑的小吃货
Eat 西瓜
Eat 甜瓜
Eat 哈密瓜
[Timer( sleep )] 2
Eat 苹果
Eat 橘子
Eat 香蕉
[Timer( sleep )] 3
[Timer( sleep )] 4
Eat 撑死了
[Task] ==========Stop==========
*/
正规作答结束,以下是原答案:
民科解法,欢迎来喷。强迫症,没有使用 任务队列,和 @xiaoboost 答案不同的是,不支持 LazyMan('Hank').sleepFirst(2).sleep(3).eat('lunch').sleep(4).eat('dinner'); 这种方式调用。
不在乎中间过程,只在乎结果。
稍后用队列的方法,重写一遍。
function LazyMan(nick){
var obj = {
data : {},
echo : function( str , str2 ){
console.log( str + ' ' + str2 );
},
hello : function( nick ){
this.data.nick = nick || this.data.nick;
setTimeout( (function(){
if( ! this.data.waiting ){
this.echo('Hi', this.data.nick);
}
}).bind(this), 16);
return this;
},
eat : function( eat ){
this.data.eat = eat || this.data.eat;
setTimeout( (function(){
if( ! this.data.sleep ){
this.echo('Eat', this.data.eat);
}
}).bind(this), 16);
return this;
},
sleep : function( timer ){
this.data.sleep = true;
setTimeout( (function(){
this.data.sleep = false;
this.eat();
}).bind(this), timer * 1000);
return this;
},
sleepFirst : function( timer ){
this.data.waiting = true;
this.data.sleep = true;
setTimeout( (function(){
this.data.waiting = false;
this.hello();
this.data.sleep = false;
this.eat();
}).bind(this), timer * 1000);
return this;
}
};
return obj.hello(nick);
}
这篇关于javascript - 一个面试题,有啥想法么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文