LazyMan题目讲解
来源:互联网 发布:java车辆管理系统源码 编辑:程序博客网 时间:2024/05/18 18:00
题目是从知乎上看到的:https://zhuanlan.zhihu.com/p/28892523?utm_medium=social&utm_source=qq
一、题目
实现一个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
以此类推。
二、解题思路
1.整体是一个js的面向对象编程的题目
2.涉及到异步控制的思想
3.执行顺序不同于调用顺序
4.可以考虑内部维护一个数组控制调用顺序
5.可以考虑使用Promise实现
6.可以考虑使用async实现
三、解题代码实现
1.ES5原生代码实现——个人手打调试
function Man(name) { this.actions = []; this.current = 0; var helloFunc = function () { console.log("Hi This is " + name + "!"); this.act(); }.bind(this) this.addAction(helloFunc); setTimeout(function () { this.act(); }.bind(this), 0); } // 调用下一个动作 Man.prototype.act = function () { var actions = this.actions; return actions[this.current] && actions[this.current++](); } // 向动作队列添加动作 Man.prototype.addAction = function (func, isFirst) { if (!isFirst) { this.actions.push(func); } else { this.actions.unshift(func); } } // 休眠 Man.prototype.sleep = function (time) { var sleepFunc = function () { setTimeout(function () { console.log("Wake up after " + time + "ms"); this.act(); }.bind(this), time) }.bind(this); this.addAction(sleepFunc); return this; } // 吃饭 Man.prototype.eat = function (food) { var eatFunc = function () { console.log("Eat " + food + "~"); this.act(); }.bind(this); this.addAction(eatFunc); return this; } // 睡觉优先 Man.prototype.sleepFirst = function (time) { var sleepFirstFunc = function () { setTimeout(function () { console.log("Wake up after " + time + "ms"); this.act(); }.bind(this), time) }.bind(this); this.addAction(sleepFirstFunc, true); return this; } function LazyMan(name) { return new Man(name); }
重点代码解析
var helloFunc = function () { console.log("Hi This is " + name + "!"); this.act(); }.bind(this)
如果不使用.bind(this)
那么this
指向哪里?答案是 this.actions
为什么会出现这种情况呢?
javascript的this
指向执行时的上下文对象
那么this.act()何时执行呢?答案是
return actions[this.current] && actions[this.current++]();
所以必须使用.bind(this)
改变this的指向
简化版可以参考这个代码:
var a = [0,1,2,function(){console.log(this)}]; a[3](); 输出结果为:[0, 1, 2, ƒ]
2.ES6语法实现——ES6对this的控制简直完美,会ES5的实现ES6简直so easy
class Man{ constructor(name){ this.actions = []; this.current = 0; var helloFunc = () =>{ console.log("Hi This is " + name + "!"); this.act(); } this.addAction(helloFunc); setTimeout(() =>{ this.act(); }, 0) } act(){ var actions = this.actions; return actions[this.current] && actions[this.current++](); } addAction(func, isFirst){ if(!isFirst){ this.actions.push(func) }else{ this.actions.unshift(func) } } eat(food){ var eatFunc = () =>{ console.log("Eat " + food + "~"); this.act(); } this.addAction(eatFunc) return this; } sleep(time){ var sleep = () =>{ setTimeout(() => { console.log("Wake up after " + time + "ms"); this.act(); }, time) } this.addAction(sleep); return this; } sleepFirst(time){ var sleepFirst = () =>{ setTimeout(() =>{ console.log("Wake up after " + time + "ms"); this.act(); }, time) } this.addAction(sleepFirst, true) return this; } } function LazyMan(name) { return new Man(name) }
3.Promise语法实现——知乎网友南塔托给出的答案
对于这个答案我只能说如此精辟的解法要给一个大大的赞,使我对Promise
的认识更深了一层。
class Lazy { constructor(name) { this.sleepFirstTime = 0; this.promise = Promise.resolve().then( () => this.sleepFirstTime && this._sleep(this.sleepFirstTime) ).then(() => { console.log(`Hi! This is ${name}!`); }); } sleepFirst(time) { this.sleepFirstTime = time; return this; } eat(food) { this.promise = this.promise.then(() => { console.log(`Eat ${food}~`); }); return this; } sleep(time) { this.promise = this.promise.then(() => this._sleep(time)); return this; } _sleep(time) { return new Promise((next) => { setTimeout(() => { console.log(`Wake up after ${time}`); next(); }, time); }); } } function LazyMan(name) { return new Lazy(name); }
重点代码解析
constructor(name) { this.sleepFirstTime = 0; // Promise.resolve()创建一个Promise对象执行后面的函数 this.promise = Promise.resolve().then( // this.sleepFirstTime为0时后面的函数不会执行 () => this.sleepFirstTime && this._sleep(this.sleepFirstTime) ).then(() => { console.log(`Hi! This is ${name}!`); }); }
假设执行该函数
LazyMan(“Hank”).sleepFirst(2000).sleep(2000).eat(“supper”)
【注意】构造函数初始化时仅执行了this.promise = Promise.resolve()
此时的this.promise仅仅是一个Promise对象 .then
会在.eat("super")
结束后才调用
然后.sleepFirst
等函数对this.promise
进行了改造
最后各种.then
方法会链式调用达到所需效果
- LazyMan题目讲解
- LazyMan
- Lazyman
- 一些基本知识题目讲解
- 竞赛题目讲解
- Promise实现的lazyman
- js实现lazyMan
- 简易的lazyman实现
- lazyman js流程控制
- 计算几何之题目讲解
- 华为性格测试题目讲解
- LazyMan深入解析和实现
- js实现lazyman(流程控制)
- LazyMan深入解析和实现
- 2016华为软件开发题目讲解
- Android面试题目整理与讲解
- Android面试题目整理与讲解
- Android面试题目整理与讲解
- Web
- 使用JavaMail通过SMTP协议发送局域网(内网)邮件
- Unity技巧总结03 转美术数字动态设置
- Submit string: submit:trigger=0,bugtype=2,modulename=
- Linux 乱码问题
- LazyMan题目讲解
- vs2015在Debug模式下运行出现"应用程序无法正常启动(0x000007b)"的错误解决方法
- linux命令
- 布隆过滤器(Bloom Filter)详解
- awk 整理
- ubuntu 下 LNMP git composer 等安装配置资料汇总
- WPF拙见
- [BZOJ]4448: [Scoi2015]情报传递 主席树+LCA
- SPOJ DISUBSTR 后缀数组