>

微信LazyMan笔试题的深入解析和实现,LazyMan的深入

- 编辑:至尊游戏网站 -

微信LazyMan笔试题的深入解析和实现,LazyMan的深入

WechatLazyMan笔试题的历历在目剖判和兑现

2017/02/03 · JavaScript · Javascript, 异步

原稿出处: wall_wxk   

以下是本人copy自网络的面试题最早的文章:

生机勃勃、题目介绍

以下是自个儿copy自网络的面试题最先的小说:

贯彻贰个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

就那样推算。

贯彻二个LazyMan,能够依据以下方法调用:LazyMan输出:Hi! This is Hank! LazyMan.sleep.eat输出Hi! This is Hank!//等待10秒..Wake up after 10Eat dinner~ LazyMan.eat.eat输出Hi This is Hank!Eat dinner~Eat supper~ LazyMan.sleepFirst.eat输出//等待5秒Wake up after 5Hi This is Hank!Eat supper 由此及彼。

二、标题考查的点

先注明:笔者不是Wechat职员和工人,考察的点是自己想见的,只怕不是,哈哈!

1.方法链式调用
2.类的接收和面向对象编制程序的思绪
3.设计情势的选用
4.代码的解耦
5.起码知识标准化,也即 迪米特法则(Law of 德姆eter卡塔 尔(英语:State of Qatar)
6.代码的书写结议和命名

先注解:作者不是Wechat工作者,侦查的点是自家想见的,大概不是,哈哈!

三、标题思路拆解解析

1.看难题输出示例,能够规定那是拟人化的输出,也正是说:应该编写一个类来定义大器晚成类人,叫做LazyMan。能够出口名字、吃饭、睡觉等作为。
2.从出口的语句能够看看,sleepFrist的预先级是最高的,其余表现的先行级生机勃勃致。
3.从三个例证来看,都得先调用LazyMan来先导化一人,本事延续持继续展览现,所以LazyMan是一个接口。
4.句子是按调用方法的程序进行依次履行的,是贰个行列。

1.措施链式调用 2.类的施用和面向对象编制程序的思绪 3.设计情势的应用 4.代码的解耦 5.起码知识规范化,也即 迪米特法规(Law of 德姆eter卡塔尔6.代码的书写结交涉命名

四、采用观望者情势实现代码

4.1 选取模块方式来编排代码

JavaScript

(function(window, undefined){ })(window);

1
2
3
(function(window, undefined){
 
})(window);

4.2 声美赞臣(Meadjohnson卡塔尔个变量taskList,用来存款和储蓄供给队列消息

JavaScript

(function(window, undefined){ var taskList = []; })(window);

1
2
3
(function(window, undefined){
    var taskList = [];
})(window);

队列中,单个项的存放设计为叁个json,存款和储蓄须要接触的新闻,以至艺术施行时索要的参数列表。举个例子LazyMan(‘汉克’),供给的蕴藏消息如下。

JavaScript

{ 'msg':'LazyMan', 'args':'Hank' }

1
2
3
4
{
    'msg':'LazyMan',
    'args':'Hank'
}

当实行LazyMan方法的时候,调用订阅方法,将索要实践的新闻存入taskList中,缓存起来。
仓库储存的消息,会先保留着,等宣布办法实行领取,实践和出口。

4.3 订阅方法

订阅方法的调用方式设计:subscribe("lazyMan", "Hank")

JavaScript

(function(window, undefined){ var taskList = []; // 订阅 function subscribe(){ var param = {}, args = Array.prototype.slice.call(arguments); if(args.length < 1){ throw new Error("subscribe 参数不能够为空!"); } param.msg = args[0]; // 音信名 param.args = args.slice(1); // 参数列表 if(param.msg == "sleepFirst"){ taskList.unshift(param); }else{ taskList.push(param); } } })(window);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
(function(window, undefined){
    var taskList = [];
 
    // 订阅
    function subscribe(){
        var param = {},
            args = Array.prototype.slice.call(arguments);
 
        if(args.length < 1){
            throw new Error("subscribe 参数不能为空!");
        }
 
        param.msg = args[0]; // 消息名
        param.args = args.slice(1); // 参数列表
 
        if(param.msg == "sleepFirst"){
            taskList.unshift(param);
        }else{
            taskList.push(param);
        }
    }
})(window);

用八个param变量来组织好内需仓库储存的新闻,然后push进taskList中,缓存起来。
刻意的,即使是sleepFirst,则停放在队列尾部。

4.4 公布办法

JavaScript

(function(window, undefined){ var taskList = []; // 订阅方法 代码... // 公布 function publish(){ if(taskList.length > 0){ run(taskList.shift()); } } })(window);

1
2
3
4
5
6
7
8
9
10
11
12
(function(window, undefined){
    var taskList = [];
 
        // 订阅方法 代码...
 
    // 发布
    function publish(){
        if(taskList.length > 0){
            run(taskList.shift());
        }
    }
})(window);

将队列中的存款和储蓄音信读抽取来,交给run方法(暂定,后续实现)去施行。这里节制每一趟发表只进行二个,以保持队列之中的主意能够挨个试行。
除此以外,这里运用shift()方法的缘故是,抽出三个,就在队列中删除那叁个,幸免再度实施。

4.5 实现LazyMan类

JavaScript

// 类 function LazyMan(){}; LazyMan.prototype.eat = function(str){ subscribe("eat", str); return this; }; LazyMan.prototype.sleep = function(num){ subscribe("sleep", num); return this; }; LazyMan.prototype.sleepFirst = function(num){ subscribe("sleepFirst", num); return this; };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 类
function LazyMan(){};
 
LazyMan.prototype.eat = function(str){
    subscribe("eat", str);
    return this;
};
 
LazyMan.prototype.sleep = function(num){
    subscribe("sleep", num);
    return this;
};
 
LazyMan.prototype.sleepFirst = function(num){
    subscribe("sleepFirst", num);
    return this;
};

将LazyMan类实现,具有eat、sleep、sleepFrist等行为。
接触一遍作为,就在taskList中著录一遍,并回到当前指标,以支撑链式调用。

4.6 完成出口console.log的包裹情势

JavaScript

// 输出文字 function lazyManLog(str){ console.log(str); }

1
2
3
4
// 输出文字
function lazyManLog(str){
    console.log(str);
}

为啥还要为console.log包装后生可畏层,是因为在实战项目中,产经平日会改正出口提醒的UI。要是每豆蔻梢头处都用console.log直接调用,那改起来就麻烦超多。
此外,即便要包容IE等低级版本浏览器,也足以很有益于的改良。
也就是DRY原则(Don’t Repeat Youself)。

4.7 达成具体试行的措施

JavaScript

// 具体方法 function lazyMan(str){ lazyManLog("Hi!This is "+ str +"!"); publish(); } function eat(str){ lazyManLog("Eat "+ str +"~"); publish(); } function sleep(num){ setTimeout(function(){ lazyManLog("Wake up after "+ num); publish(); }, num*1000); } function sleepFirst(num){ setTimeout(function(){ lazyManLog("Wake up after "+ num); publish(); }, num*1000); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 具体方法
function lazyMan(str){
    lazyManLog("Hi!This is "+ str +"!");
 
    publish();
}
 
function eat(str){
    lazyManLog("Eat "+ str +"~");
    publish();
}
 
function sleep(num){
    setTimeout(function(){
        lazyManLog("Wake up after "+ num);
 
        publish();
    }, num*1000);
 
}
 
function sleepFirst(num){
    setTimeout(function(){
        lazyManLog("Wake up after "+ num);
 
        publish();
    }, num*1000);
}

此处的第一是减轻setTimeout实行时会延迟调用,也即线程异步试行的标题。唯有该措施施行成功后,再发布一回音信publish(),提醒能够实行下三个队列音信。不然,就能一贯等候。

4.8 完结run方法,用于识别要调用哪个具体方法,是三个总的调整台

JavaScript

// 鸭子叫 function run(option){ var msg = option.msg, args = option.args; switch(msg){ case "lazyMan": lazyMan.apply(null, args);break; case "eat": eat.apply(null, args);break; case "sleep": sleep.apply(null,args);break; case "sleepFirst": sleepFirst.apply(null,args);break; default:; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
// 鸭子叫
function run(option){
    var msg = option.msg,
        args = option.args;
 
    switch(msg){
        case "lazyMan": lazyMan.apply(null, args);break;
        case "eat": eat.apply(null, args);break;
        case "sleep": sleep.apply(null,args);break;
        case "sleepFirst": sleepFirst.apply(null,args);break;
        default:;
    }
}

以此办法有一点点像鸭式辨型接口,所以注释叫鸭子叫
run方法选用队列中的单个音信,然后读抽取来,看音信是什么类型的,然后施行相应的办法。

4.9 暴光接口LazyMan,让外界能够调用

JavaScript

(function(window, undefined){ // 超级多代码... // 揭露接口 window.LazyMan = function(str){ subscribe("lazyMan", str); setTimeout(function(){ publish(); }, 0); return new LazyMan(); }; })(window);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
(function(window, undefined){
        // 很多代码...
 
    // 暴露接口
    window.LazyMan = function(str){
        subscribe("lazyMan", str);
 
        setTimeout(function(){
            publish();
        }, 0);
 
        return new LazyMan();
    };
})(window);

接口LazyMan里面包车型地铁publish方法必得接纳setTimeout实行调用。这样能让publish()实施的线程延后,挂起。等链式方法都试行实现后,线程空闲下来,再举行该publish()
除此以外,这是一个对外接口,所以调用的时候,同一时间也会new 二个新的LazyMan,并重返,以供调用。

1.看难题输出示例,能够规定那是拟人化的出口,也正是说:应该编写一个类来定义黄金年代类人,叫做LazyMan。能够输有名字、吃饭、睡觉等行为。 2.从输出的语句能够看见,sleepFrist的事先级是参天的,别的展现的优先级生龙活虎致。 3.从八个例证来看,都得先调用LazyMan来开首化一人,手艺世襲持续行为,所以LazyMan是八个接口。 4.句子是按调用方法的程序举行每一种施行的,是三个行列。

五、总结

1. 好处

运用观察者情势,让代码能够解耦到合理的等级次序,使前期维护越发有利。
比方自个儿想改良eat方法,笔者只须求关切eat()LazyMan.prototype.eat的兑现。其余地方,笔者都可以不用关爱。那就符合了足足知识标准化

2. 不足
LazyMan.prototype.eat这种方法的参数,其实能够用arguments代替,作者没写出来,怕弄得太复杂,就留个优化点呢。
利用了unshift和shift方法,未有思忖到低版本IE浏览器的合作。

4.1 接受模块格局来编排代码

六、完整源码和线上demo

豆蔻梢头体化源码已经身处本人的gitHub上

源码入口:

demo访谈地址:

demo需求开荒调节台,在调控桃园疗养代码。

(function(window, undefined){});

七、番外

网络有人也落成了lazyMan,不过得以完结的主意本人不是相当高兴和认可,可是也是风流罗曼蒂克种思路,这里顺便贴出来给大伙看看。
哪些落到实处二个LazyMan:

1 赞 收藏 评论

图片 1

4.2 声多美滋个变量taskList,用来囤积要求队列新闻

(function(window, undefined){ var taskList = [];});

队列中,单个项的存款和储蓄设计为一个json,存款和储蓄必要接触的音信,以至艺术施行时要求的参数列表。譬如LazyMan,需求的储存音信如下。

{ 'msg':'LazyMan', 'args':'Hank'}

当试行LazyMan方法的时候,调用订阅方法,将索要奉行的音讯存入taskList中,缓存起来。 存储的信息,会先保留着,等文告办法开展领取,推行和输出。

4.3 订阅方法

订阅方法的调用方式设计:subscribe("lazyMan", "Hank")

(function(window, undefined){ var taskList = []; // 订阅 function subscribe(){ var param = {}, args = Array.prototype.slice.call(arguments); if(args.length < 1){ throw new Error("subscribe 参数不能为空!"); } param.msg = args[0]; // 消息名 param.args = args.slice; // 参数列表 if(param.msg == "sleepFirst"){ taskList.unshift; }else{ taskList.push; } }});

用四个param变量来公司好内需仓库储存的音讯,然后push进taskList中,缓存起来。 特别的,尽管是sleepFirst,则停放在队列尾部。

4.4 发布办法

(function(window, undefined){ var taskList = []; // 订阅方法 代码... // 发布 function publish(){ if(taskList.length > 0){ run(taskList.shift;

将队列中的存款和储蓄新闻读抽出来,交给run方法``去施行。这里约束每回发表只举行二个,以维持队列之中的艺术能够挨个推行。 别的,这里运用shift()方法的原因是,收取一个,就在队列中删去这些,制止双重实行。

4.5 实现LazyMan类

// 类function LazyMan(){};LazyMan.prototype.eat = function{ subscribe("eat", str); return this;};LazyMan.prototype.sleep = function{ subscribe("sleep", num); return this;};LazyMan.prototype.sleepFirst = function{ subscribe("sleepFirst", num); return this;};

将LazyMan类达成,具备eat、sleep、sleepFrist等作为。 触发贰遍表现,就在taskList中记录三遍,并重返当前目的,以帮助链式调用。

4.6 完毕出口console.log的卷入方式

// 输出文字function lazyManLog{ console.log;}

干什么还要为console.log包装生龙活虎层,是因为在实战项目中,产经平时会改进出口提醒的UI。倘若每风度翩翩处都用console.log间接调用,那改起来就麻烦非常多。 其它,假使要宽容IE等低级版本浏览器,也能够很实惠的校订。 也正是D库罗德Y原则(Don't Repeat Youself卡塔尔国。

4.7 完成具体实践的主意

// 具体方法function lazyMan{ lazyManLog("Hi!This is "+ str +"!"); publish();}function eat{ lazyManLog("Eat "+ str +"~"); publish();}function sleep{ setTimeout(function(){ lazyManLog("Wake up after "+ num); publish(); }, num*1000); }function sleepFirst{ setTimeout(function(){ lazyManLog("Wake up after "+ num); publish(); }, num*1000);}

那边的最首假设缓慢解决setTimeout试行时会延迟调用,也即线程异步试行的主题素材。独有该措施施行成功后,再发布叁回音信publish(),指示能够推行下贰个行列音讯。否则,就能够一向等待。

4.8 完成run方法,用于识别要调用哪个具体方法,是一个总的调控台

// 鸭子叫function run{ var msg = option.msg, args = option.args; switch{ case "lazyMan": lazyMan.apply(null, args);break; case "eat": eat.apply(null, args);break; case "sleep": sleep.apply(null,args);break; case "sleepFirst": sleepFirst.apply(null,args);break; default:; }}

以此艺术有一些像鸭式辨型接口,所以注释叫鸭子叫。 run方法接受队列中的单个音讯,然后读抽取来,看音信是什么品种的,然后实行相应的主意。

4.9 暴光接口LazyMan,让外界能够调用

(function(window, undefined){ // 很多代码... // 暴露接口 window.LazyMan = function{ subscribe("lazyMan", str); setTimeout(function(){ publish; return new LazyMan;

接口LazyMan里面包车型大巴publish方法必须利用setTimeout举办调用。那样能让publish()实行的线程延后,挂起。等链式方法都试行达成后,线程空闲下来,再实施该publish()。 别的,那是八个对外接口,所以调用的时候,同时也会new 七个新的LazyMan,并赶回,以供调用。

1. 好处

利用观望者格局,让代码能够解耦到合理的品位,使中期维护越发实惠。 比如作者想改善eat方法,作者只要求关注eat()LazyMan.prototype.eat的落实。别的地点,小编都得以不用关爱。那就相符了起码知识标准化

2. 不足 LazyMan.prototype.eat这种艺术的参数,其实能够用arguments取代,小编没写出来,怕弄得太复杂,就留个优化点吗。 使用了unshift和shift方法,未有设想到低版本IE浏览器的合营。

完整源码已经位于自家的gitHub上

源码入口:

demo访谈地址:

demo须求开荒调整台,在调整台北调和代码。

网络有人也兑现了lazyMan,可是落到实处的点子自己不是很喜欢和承认,不过也是意气风发种思路,这里顺便贴出来给大伙看看。怎么样贯彻四个LazyMan:

赏识作者作品的意中人,扫描以下二维码,关怀自身的私家技能博客,小编的才能小说会第临时间在博客上更新点击链接wall的个人博客

图片 2wall的私人民居房博客

本文由设计建站发布,转载请注明来源:微信LazyMan笔试题的深入解析和实现,LazyMan的深入