javascript - 一个面试题,有啥想法么?

查看:97
本文介绍了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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆