Open zeroone001 opened 5 years ago
class LazyManClass {
constructor(name) {
this.name = name
this.queue = []
console.log(`Hi I am ${name}`)
setTimeout(() => {
this.next()
},0)
}
sleepFirst(time) {
const fn = () => {
setTimeout(() => {
console.log(`等待了${time}秒...`)
this.next()
}, time)
}
this.queue.unshift(fn)
return this
}
sleep(time) {
const fn = () => {
setTimeout(() => {
console.log(`等待了${time}秒...`)
this.next()
},time)
}
this.queue.push(fn)
return this
}
eat(food) {
const fn = () => {
console.log(`I am eating ${food}`)
this.next()
}
this.queue.push(fn)
return this
}
next() {
const fn = this.queue.shift()
fn && fn()
}
}
function LazyMan(name) {
return new LazyManClass(name)
}
function LazyMan(name){
var lazy = new Lazy(name);
lazy.init();
return lazy;
}
function Lazy(name){
this.name = name;
this.fns = [];
this.init = function(){
var _this = this;
_this.print("I am "+this.name);
setTimeout(function(){
_this.next();
}, 0);
};
this.eat = function(food){
var _this = this;
_this.fns.push(function(){
_this.print("I am eating "+food);
_this.next();
});
return this;
};
this.sleep= function(time){
var _this = this;
_this.fns.push(function(){
setTimeout(function(){
_this.print("等待了" + time + "秒");
_this.next();
}, 1000*time);
});
return this;
};
this.sleepFirst = function(time){
var _this = this;
_this.fns.unshift(function(){
setTimeout(function(){
_this.print("等待了" + time + "秒");
_this.next();
}, 1000*time)
});
return this;
};
this.print = function(something){
console.log(something);
};
this.next = function(){
this.fns.length>0 && this.fns.shift()();
};
}
function LazyMan (name) { class Man { constructor (name) { this._queues = [] console.log(`Hi I am ${name}`) Promise.resolve().then(() => { this.next() }) return this } _sleep = (time) => { return new Promise(resolve => setTimeout(resolve, time * 1000)) } eat (type) { this._queues.push(() => { console.log(`I am eating ${type}`) this.next(); }) return this } sleepFirst (time) { this._queues.unshift(() => { this._sleep(time).then(() => { console.log(`等待了${time}秒`) this.next() }) }) return this } sleep (time) { this._queues.push(() => { this._sleep(time).then(() => { console.log(`等待了${time}秒`) this.next() }) }) return this } next () { const fn = this._queues.shift(); fn && fn() } } return new Man(name) } LazyMan('Tom'); LazyMan('Tom').sleep(10).eat('lunch') LazyMan('Tom').eat('lunch').sleep(10).eat('dinner') LazyMan('Tom').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food')
class LazyMan {
constructor(name) {
this.task = [];
this.task.push(
() => {
console.log(`My name is ${name}`);
this.next();
}
)
setTimeout(() => { this.next() })
}
eat(val) {
this.task.push(
() => {
console.log(`吃 ${val}`);
this.next();
}
)
return this;
}
sleep(sec) {
this.task.push(
() => {
setTimeout(() => {
console.log(`睡 ${sec} 秒`);
this.next();
}, sec * 1000);
}
)
return this;
}
next() {
let fn = this.task.shift();
fn && fn();
}
}
let lazyCzh = new LazyMan('czh');
lazyCzh.eat('apple').eat('banana').sleep(3).eat('orange');
Proxy 版本
function LazyMan(username) {
console.log(' Hi I am ' + username);
var temp = {
taskList: [],
sleepFirst(timeout) {
return () => {
setTimeout(() => {
console.log(`等待了${timeout}秒...`);
this.next();
}, timeout * 1000);
};
},
sleep(timeout) {
return () => {
setTimeout(() => {
console.log(`等待了${timeout}秒...`);
this.next();
}, timeout * 1000);
};
},
eat(type) {
return () => {
console.log(`I am eating ${type}`);
this.next();
};
},
next() {
var fn = this.taskList.shift();
fn && fn();
}
};
var proxy = new Proxy(temp, {
get(target, key, receiver) {
return function(...rest) {
if (key === 'sleepFirst') {
target.taskList.unshift(target[key](rest));
} else {
target.taskList.push(target[key](rest));
}
return receiver;
};
}
});
setTimeout(() => {
temp.next();
}, 0);
return proxy;
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
// Hi I am Tony
// 等待了5秒...
// I am eating lunch
// I am eating dinner
// 等待了10秒...
// I am eating junk food
function LazyMan(name) {
console.log("Hi I am Tony");
return {
sleepTime: 0,
firstSleepTime: 0,
sleep: function(second) {
let time = 0;
function logText() {
setTimeout(() => {
console.log("等待了十秒...");
}, time);
}
setTimeout(() => {
time = second * 1000 + this.firstSleepTime * 1000;
logText();
}, 0);
this.sleepTime = this.sleepTime + second;
return this;
},
eat: function(meal) {
let time = this.sleepTime * 1000;
function logText() {
setTimeout(() => {
console.log("I am eating " + meal);
}, time);
}
setTimeout(() => {
time = time + this.firstSleepTime * 1000;
logText();
}, 0);
return this;
},
sleepFirst: function(second) {
let time = second * 1000;
setTimeout(() => {
console.log("等待了5秒");
}, time);
this.firstSleepTime = second;
return this;
}
};
};
写个链表实现
class Node {
constructor(func = null) {
this.func = func;
this.next = null;
}
async exec() {
if (this.func) {
await this.func();
}
if (this.next && this.next.func) {
this.next.exec();
}
}
}
function delayFunc(delay) {
return new Promise(resolve => {
setTimeout(() => {
console.log(`等待了${delay}秒...`);
resolve();
}, delay * 1000);
});
}
class Lazy {
constructor(name) {
this.name = name;
this.head = new Node();
this.current = this.head;
Promise.resolve().then(() => this.head.exec());
}
eat(sth) {
const log = () => {
console.log("I am eating " + sth);
};
this.current.next = new Node(log);
this.current = this.current.next;
return this;
}
sleep(delay) {
this.current.next = new Node(() => delayFunc(delay));
this.current = this.current.next;
return this;
}
sleepFirst(delay) {
let head = new Node(() => delayFunc(delay));
if (!this.head.func) {
head.next = this.head.next;
} else {
head.next = this.head;
}
this.head = head;
return this;
}
}
function LazyMan(name) {
console.log("I am " + name);
return new Lazy(name);
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
function LazyMan(name){
return new class LazyMan{
constructor(name){
this.tasks=[]
this.hello(name)
setTimeout(this.next.bind(this),0)
}
log(str){console.log(str);return true}
next(){
var fn=this.tasks.shift()
fn&&fn.apply(this)
}
hello(name){
this.tasks.push(()=>this.log('hello '+name)&&this.next())
return this
}
sleepfirst(time){
this.tasks.unshift(()=>this.log('sleep '+time)&&setTimeout(this.next.bind(this),time))
return this
}
eat(what){
this.tasks.push(()=>this.log('eat '+what)&&this.next())
return this
}
sleep(time){
this.tasks.push(()=>this.log('sleep '+time)&&setTimeout(this.next.bind(this),time))
return this
}
}(name)
}
/**
* 普通 eat方法, 存放在立即执行队列中, 用settimeout来执行
* sleep 方法 每次调用这个方法, 都单独开一个定时器, 把新的任务加入到这个队列
* sleepFirst方法 把立即执行的任务队列的任务 塞到新的定时器任务队列
*/
class LazymanClass {
constructor (_name = '') {
this._immediateTask = []
this._immediateTimer = null
this._sleepTaskMap = {}
this._curSleepTaskKey = null
this._log(`Hi i am ${_name}`)
}
eat (meal) {
// 添加新任务之前 清空之前的 立即定时器
this._immediateTimer && clearTimeout(this._immediateTimer)
const _eat = (meal) => {
this._log(`i am eating ${meal}`)
}
if (this._curSleepTaskKey === null) {
this._immediateTask.push(_eat.bind(this, meal))
} else {
this._sleepTaskMap[this._curSleepTaskKey].push(_eat.bind(this, meal))
}
this._immediateTimer = setTimeout(() => {
this._runImmeadiateTask()
})
return this
}
sleep (second) {
const key = Math.random()
this._curSleepTaskKey = key
this._sleepTaskMap[this._curSleepTaskKey] = []
setTimeout(() => {
this._log(`等待了${second}秒`);
this._runSleepTask(key)
}, second * 1000)
return this
}
sleepFirst (second) {
const key = Math.random()
this._curSleepTaskKey = key
this._sleepTaskMap[key] = []
this._immediateTask.map(task => {
this._sleepTaskMap[key].push(task)
})
this._immediateTask = []
setTimeout(() => {
this._log(`等待了${second}秒`);
this._runSleepTask(key)
}, second * 1000)
return this
}
_runImmeadiateTask () {
this._immediateTask.map(task => {
typeof task === 'function' && task()
})
this._immediateTask = []
}
_runSleepTask (key) {
this._sleepTaskMap[key].map(task => {
typeof task === 'function' && task()
})
this._sleepTaskMap[key] = []
}
_log(str) {
console.log(str)
}
}
function LazyMan(name) {
return new LazymanClass(name)
}
const test = () => {
// LazyMan('Tony')
// LazyMan('Tony').eat('lunch')
// LazyMan('Tony').sleep(2).eat('lunch')
// LazyMan('Tony').eat('lunch').sleep(2).eat('diner')
LazyMan('Tony').eat('lunch').eat('diner').sleepFirst(1).sleep(2).eat('junk food')
}
test()
class LazyManClass {
constructor(props){
this.sub = []
console.log(`Hi I am ${props}`)
setTimeout(()=>{
this.start()
},0)
}
eat (params){
this.sub.push(function(){
console.log(`I am eating ${params}`)
})
return this
}
sleepFirst(s){
this.sub.unshift(this.delay(s))
// 这边还没有返回 同步就继续执行了
return this
}
delay(s) {
return () => {
return new Promise(resolve => {
setTimeout(function () {
console.log(`等待了${s}秒...`)
resolve()
},s * 1000)
})
}
}
sleep (s){
this.sub.push(this.delay(s))
// 这边还没有返回 同步就继续执行了
return this
}
async start(){
for (const iterator of this.sub) {
await iterator()
}
}
}
function LazyMan(props) {
return new LazyManClass(props)
}
LazyMan('Tony').eat('lunch').eat('diner').sleepFirst(1).sleep(2).eat('junk food')
// Hi I am Tony
// 等待了5秒...
// I am eating lunch
// I am eating dinner
// 等待了10秒...
// I am eating junk food
function LazyMan(name) {
if (!(this instanceof LazyMan)) {
return new LazyMan(name);
}
this.name = name;
this.delayTime = 0;
this.tasks = [];
console.log(`Hi I am ${this.name}`);
this._ready();
}
LazyMan.prototype._ready = function () {
setTimeout(() => {
setTimeout(() => {
console.log(`等待了${this.delayTime}秒...`);
this._doTasks();
}, this.delayTime * 1000);
}, 0);
}
LazyMan.prototype._doTasks = function () {
const tasks = this.tasks;
if (tasks.length === 0) return;
const {delayTime, callback} = tasks[0];
setTimeout(() => {
callback && callback();
tasks.shift();
this._doTasks();
}, delayTime);
}
LazyMan.prototype.eat = function (foods) {
this.tasks.push({
delayTime: 0,
callback() {
console.log(`I am eating ${foods}`);
},
});
return this;
}
LazyMan.prototype.sleep = function (seconds) {
if (seconds >= 0) {
this.tasks.push({
delayTime: seconds * 1000,
callback() {
console.log(`等待了${seconds}秒...`)
}
});
}
return this;
}
LazyMan.prototype.sleepFirst = function (seconds) {
if (seconds > 0) {
this.delayTime = seconds;
}
return this;
}
function LazyMan(name) {
if (this instanceof LazyMan) {
this.task = [];
this.log('Hi I am '+ name);
setTimeout(() => {
this.next();
}, 0);
}
return (this instanceof LazyMan) && this || new LazyMan(name);
}
LazyMan.prototype.log = console.log;
LazyMan.prototype.next = function() {
const [fn, ...tail] = this.task;
fn && (this.task = tail) && fn();
}
LazyMan.prototype.eat = function(food) {
this.task = [
...this.task,
() => {
this.log('I am eating '+ food);
this.next();
}
]
return this;
}
LazyMan.prototype.sleep = function(timeout) {
this.task = [
...this.task,
() => {
setTimeout(() => {
this.next();
}, timeout * 1000);
}
]
return this;
}
LazyMan.prototype.sleepFirst = function(timeout) {
this.task = [
() => {
setTimeout(() => {
this.next();
}, timeout * 1000)
},
...this.task
]
return this;
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(1).sleep(2).eat('junk food');
// 写一个 setTimeout 就可以了。
class lazyManClass {
constructor(name){
this.taskList = []
this.init(name)
}
init(name){
var _this = this
this.taskList.push({
time: 0, // 是否是异步
fn:(function(s){ // 函数自执行
return function() {
_this.exec()
console.log('Hi I am ', s)
}
})(name)
})
this.exec()
return this
}
eat(str) {
var _this = this
this.taskList.push({
time: 0,
fn: (function(s){
return function() {
_this.exec()
console.log('I am eating ', s)
}
})(str)
})
return this
}
sleep(t){
var _this = this
this.taskList.push({
time: t * 1000,
fn: (function(time){
return function() {
_this.exec()
console.log(`等待了${time}秒...`)
}
})(t)
})
return this
}
sleepFirst(t) {
var _this = this
this.taskList.unshift({
time: t * 1000,
fn: (function(time){
return function() {
_this.exec()
console.log(`等待了${time}秒...`)
}
})(t)
})
return this
}
exec(){
var obj = this.taskList.shift()
if(!obj) {
return // 最后一个fn里面,也会执行 _this.exec(),这个时候taskList已经空了
}
setTimeout(() => {
obj.fn && obj.fn.call(this)
}, obj.time || 0)
}
}
function LazyMan(name) {
return new lazyManClass(name)
}
class LazyMan {
constructor (user) {
this.timeList = [];
console.log(`Hi I am ${user}`)
Promise.resolve().then(res => this.next());
}
eat (res) {
var fn = () => {
console.log(`I am eating ${res}`);
this.next();
}
this.timeList.push(fn);
return this;
}
sleep (time) {
var fn = res => {
setTimeout(res => {
console.log(`等待了${time}秒`);
this.next();
},time*1000)
}
this.timeList.push(fn);
return this;
}
next () {
var fn = this.timeList.shift();
fn && fn();
}
sleepFrist (time) {
var fn = res => {
setTimeout(res => {
console.log(`先等待了${time}秒`);
this.next();
},time*1000)
}
this.timeList.unshift(fn);
return this;
}
}
function lazyman (res) {
return new LazyMan(res)
}
_//lazyman('静静').sleep(2).eat('饺子').sleep(3).eat('面').sleepFrist(1).eat('others')
//Hi I am 静静
//先等待了1秒
//等待了2秒
//I am eating 饺子
//等待了3秒
//I am eating 面
//I am eating others_
class LazyMan {
constructor(name) {
this.tasks = []
const task = () => {
console.log(name)
}
this.tasks.push(task)
setTimeout(() => {
this.exec()
})
}
sleep(time) {
const task = () => new Promise(resolve => {
setTimeout(resolve, time)
})
this.tasks.push(task)
return this
}
sleepFirst(time) {
const task = () => new Promise(resolve => {
setTimeout(resolve, time)
})
let originTask = this.tasks.shift()
this.tasks.unshift(originTask,task)
return this
}
eat(food) {
const task = () => {
console.log(food)
}
this.tasks.push(task)
return this
}
async exec() {
for (let task of this.tasks) {
await task()
}
}
}
function LazyManClass(name){
this.name = name;
console.log('Hi I am '+name);
//存储行为列表
this.taskList = [];
//声明类行为执行函数
this.doTask = function(){
var fn = this.taskList.shift();
if(fn){
fn();
}
};
//异步执行默认行为函数
var _this = this;
setTimeout(function(){
_this.doTask();
},0);
}
LazyManClass.prototype.eat = function(food){
var _this = this;
var fn = function(){
console.log('I am eating '+food);
_this.doTask();
}
//维护行为列表
this.taskList.push(fn);
return this;
}
LazyManClass.prototype.sleepFirst = function(time){
var _this = this;
var fn = function(){
setTimeout(function(){
console.log('等待了 '+time+'秒...');
_this.doTask();
},time*1000)
}
//维护行为列表
this.taskList.unshift(fn);
return this;
}
LazyManClass.prototype.sleep = function(time){
var _this = this;
var fn = function(){
setTimeout(function(){
console.log('等待了 '+time+'秒...');
_this.doTask();
},time*1000)
}
//维护行为列表
this.taskList.push(fn);
return this;
}
//函数调用返回实例化对象
function LazyMan(name){
return new LazyManClass(name);
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
//感谢各位前辈们的代码思路,自己用es5写了一遍
有大佬能解答下next()调用的时机吗,这个运行流程我有点看不懂=。=
有大佬能解答下next()调用的时机吗,这个运行流程我有点看不懂=。=
我不是大佬,但我理解的next()应该是在LazyMan('Toney')的时候异步执行的,因为异步,所以它还没干活的时候,链式调用早结束了,taskList也把要干的活按照规则存好了,随后它开始干活,由于taskList中每个活函数执行完后又主动调用了一次next(),所以能一直把taskList中的活干完
有大佬能解答下next()调用的时机吗,这个运行流程我有点看不懂=。=
我不是大佬,但我理解的next()应该是在LazyMan('Toney')的时候异步执行的,因为异步,所以它还没干活的时候,链式调用早结束了,taskList也把要干的活按照规则存好了,随后它开始干活,由于taskList中每个活函数执行完后又主动调用了一次next(),所以能一直把taskList中的活干完
如果真是这样那就好理解了,谢谢解答!!
function LazyMan(name) {
console.log(`I am ${name}`);
var task = [];
function execute() {
var fn = task.shift();
fn && fn();
}
// delay execute
setTimeout(function() {
execute();
}, 0);
function _sleep(n = 0) {
console.log(`${name} is sleeping ${n}`);
setTimeout(function() {
execute();
}, n * 1000);
}
function _eat(food) {
console.log(`${name} is eating ${food}`);
execute();
}
var obj = {
sleep: function() {
task.push(_sleep.bind(null, ...arguments));
return obj;
},
eat: function() {
task.push(_eat.bind(null, ...arguments));
return obj;
},
sleepFirst: function() {
task.unshift(_sleep.bind(null, ...arguments));
return obj;
}
};
return obj;
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
有大佬能解答下next()调用的时机吗,这个运行流程我有点看不懂=。=
我不是大佬,但我理解的next()应该是在LazyMan('Toney')的时候异步执行的,因为异步,所以它还没干活的时候,链式调用早结束了,taskList也把要干的活按照规则存好了,随后它开始干活,由于taskList中每个活函数执行完后又主动调用了一次next(),所以能一直把taskList中的活干完
如果真是这样那就好理解了,谢谢解答!!
在constructor中, next()方法执行在 setTimeout 中,setTimeout 是一个task,当 js 运行到 setTimeout 的时候,会把他放到 task 任务队列中,等到所有的同步的任务执行完后,就会执行setTimeout 中的this.next()方法 , 这个问题的关键问题是 js 的事件队列问题 。 你可以参考这个链接详细了解 https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/7?from=groupmessage&isappinstalled=0
@GuidingStarKe
有大佬能解答下next()调用的时机吗,这个运行流程我有点看不懂=。=
我不是大佬,但我理解的next()应该是在LazyMan('Toney')的时候异步执行的,因为异步,所以它还没干活的时候,链式调用早结束了,taskList也把要干的活按照规则存好了,随后它开始干活,由于taskList中每个活函数执行完后又主动调用了一次next(),所以能一直把taskList中的活干完
如果真是这样那就好理解了,谢谢解答!!
在constructor中, next()方法执行在 setTimeout 中,setTimeout 是一个task,当 js 运行到 setTimeout 的时候,会把他放到 task 任务队列中,等到所有的同步的任务执行完后,就会执行setTimeout 中的this.next()方法 , 这个问题的关键问题是 js 的事件队列问题 。 你可以参考这个链接详细了解 https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/7?from=groupmessage&isappinstalled=0
首先谢谢解答和分享!
class LazyMan {
constructor(name){
this.name = name
this.eventQueue = []
console.log('Hi , I am %s.', name )
setTimeout(()=>{
this.drain()
},0)
}
eat(meal){
const fn = function _eat(next){
console.log('I am eating %s.',meal)
next && next()
}
this.eventQueue.push(fn)
return this
}
sleep(second){
const fn = function _sleep(next){
console.log('I am waiting %d second.', second)
setTimeout(()=>{
next && next()
},second*1000)
}
this.eventQueue.push(fn)
return this
}
sleepFirst(second){
const fn = function _sleepFirst(next){
console.log('I am waiting %d second.', second)
setTimeout(()=>{
next && next()
},second*1000)
}
this.eventQueue.splice(0,0,fn)
return this
}
drain(){
const fnComposed = this.eventQueue.reduceRight(function _reduceRight(pre,next){
return function (){
return next(pre)
}
},)
fnComposed()
}
}
const TonyStark =new LazyMan('Tony').eat('lunch').sleep(10).eat('dinner');
用了async,不需callback, 下面是两种方法放一起了。 第一种方法注释掉了,调用任务eat或者sleep或者sleepFirst时,把任务的data存放队列里,在init的方法里异步调用async executeTasks, 任务存放是同步的,先于异步的方法executeTasks执行完,在executeTasks方法里依次让任务data出列,然后执行相应的任务。
第二种是,使用next方法,每个任务最后都会调用一次next方法,把每个任务都压入队列,next的一次调用也是异步的,晚于同步的任务入列执行,next方法里让当前的任务入列,并执行。
function LazyMan(name) {
return new LazyManClass(name);
}
class LazyManClass {
constructor(name) {
this.taskList = [];
// used for method executeTasks
// this.taskDataList = [];
this.init(name);
}
init(name) {
this.printLog('name', name);
setTimeout(() => {
// the alternative solution
//this.executeTasks();
this.next();
}, 0);
}
printLog(type, data) {
const LOG_MAP = {
'name': `Hi, I am ${data}`,
'eat': `I am eating ${data}.`,
'sleep': `Waited for ${data} seconds.`,
'error': `Got something wrrong: ${data}.`
};
console.log(LOG_MAP[type]);
}
delayPromise(t) {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, t * 1000);
});
};
createTaskData(type, data) {
return { type, data };
}
createTask(type, data) {
return async () => {
if (type === 'sleep') {
try {
await this.delayPromise(data);
}
catch(e) {
this.printLog('error', e);
}
}
this.printLog(type, data);
this.next();
}
}
addTask(type, data, isFirst=false) {
if (isFirst) {
// used for method executeTasks
// this.taskList.unshift(this.createTask(type, data));
this.taskList.unshift(this.createTask(type, data));
} else {
// used for method executeTasks
// this.taskList.unshift(this.createTask(type, data));
this.taskList.push(this.createTask(type, data));
}
}
eat(str) {
this.addTask('eat', str);
return this;
}
sleep(t) {
this.addTask('sleep', t);
return this;
}
sleepFirst(t) {
this.addTask('sleep', t, true);
return this;
}
next() {
if (this.taskList.length > 0) {
let task = this.taskList.shift();
task && task();
}
}
async executeTasks() {
let taskDataList = this.taskDataList;
while (taskDataList.length > 0) {
let { type, data } = taskDataList.shift();
if (type === 'sleep') {
try {
await this.delayPromise(data);
}
catch(e) {
this.printLog('error', e);
}
}
this.printLog(type, data);
}
}
}
有没有大佬解答一下,这里传立即执行函数的返回值(函数)和直接传红字部分的函数,有什么区别吗
var fn = (n) => { console.log(n) }
你这样写,n的找不到name 你这样写,fn是个函数,而fn执行的时候是在next方法里执行的。而fn需要的的参数,你怎么获取到name呢?
在 2019-04-29 18:25:18,"kk" notifications@github.com 写道:
有没有大佬解答一下,这里传立即执行函数的返回值(函数)和直接传红字部分的函数,有什么区别吗
— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.
有没有大佬解答一下,这里传立即执行函数的返回值(函数)和直接传红字部分的函数,有什么区别吗
立即执行函数的作用是在内部函数还没有执行的时候就已经为内部函数绑定好了对应参数的值,如果不用立即函数的话也可以用bind方法
var name = '小明'
var fn = function (n){
console.log(`I am eating ${n}`)
this.next()
}.bind(null, name)
上面的代码实际上是让fn等于下面这个函数:
function (){
console.log(`I am eating 小明`)
this.next()
}
这样一来无论你在什么地方执行fn都不需要传参数了,直接fn()
不用参数也能达到和普通fn的fn(name )
效果一样了
不用类的实现,js里基本用类实现的用对象也可以实现。
LazyMan('Tony')
// Hi I am Tony
LazyMan('Tony')
.sleep(10)
.eat('lunch')
// Hi I am Tony
// 等待了10秒...
// I am eating lunch
LazyMan('Tony')
.eat('lunch')
.sleep(10)
.eat('dinner')
// Hi I am Tony
// I am eating lunch
// 等待了10秒...
// I am eating diner
LazyMan('Tony')
.eat('lunch')
.eat('dinner')
.sleepFirst(5)
.sleep(10)
.eat('junk food')
// Hi I am Tony
// 等待了5秒...
// I am eating lunch
// I am eating dinner
// 等待了10秒...
// I am eating junk food
下面是实现
let man = {
queue: []
}
function LazyMan(name) {
console.log(`Hi I am ${name}`)
setTimeout(() => {
man.next()
}, 0)
return man
}
man.eat = food => {
man.queue.push(() => {
console.log(`I am eating ${food}`)
man.next()
})
return man
}
man.sleep = timeout => {
man.queue.push(() => {
setTimeout(() => {
console.log(`等待了${timeout}秒`)
man.next()
}, timeout * 1000)
})
return man
}
man.sleepFirst = timeout => {
man.queue.unshift(() => {
setTimeout(() => {
console.log(`等待了${timeout}秒`)
man.next()
}, timeout * 1000)
})
return man
}
man.next = () => {
if (man.queue.length > 0) {
man.queue.shift()()
}
}
const LazyMan = name => new class Cp {
constructor(name) {
this.name = name;
this._queues = []
console.log(` Hi I am ${name}`)
Promise.resolve().then(() => {
this.next()
})
// return this
}
static _sleep = time => new Promise(resolve => setTimeout(resolve, time * 1000))
eat(ft) {
this._queues.push(() => {
console.log(`I am eating ${ft}`)
this.next()
})
return this
}
sleepFirst(time) {
this._queues.unshift(async () => {
await Cp._sleep(time)
console.log(`等待了 ${time} 秒`)
this.next()
})
return this
}
sleep(time) {
this._queues.push(async () => {
await Cp._sleep(time)
console.log(`等待了 ${time} 秒`)
this.next()
})
return this
}
next() {
const fn = this._queues.shift();
fn && fn()
}
}(name)
LazyMan('Tom');
LazyMan('Tom').sleep(10).eat('lunch')
LazyMan('Tom').eat('lunch').sleep(3).eat('dinner')
LazyMan('Tom').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food')
class LazyMan {
constructor(name) {
this.promise = Promise.resolve().then(() => console.log(`Hi I am ${name}`))
}
sleepFirst(time) {
this.promise = this.promise.then(() => new Promise(resolve => setTimeout(resolve, time * 1000)))
return this
}
eat(name) {
setTimeout(() => {
this.promise = this.promise.then(() => console.log(`I am eating ${name}`))
}, 0)
return this
}
sleep(time) {
setTimeout(() => {
this.promise = this.promise.then(() => new Promise(resolve => setTimeout(resolve, time * 1000)))
}, 0)
return this
}
}
不知道符不符合要求
class LazyManClass {
constructor (username) {
this.username = username
this.taskList = []
this._hello()
}
_addTask (task, data) {
clearTimeout(this.timer)
this.taskList.push(() => {
this[task](data)
})
this.timer = setTimeout(() => {
this._runTask()
})
return this
}
_runTask () {
for (let i = 0; i < this.taskList.length; i++) {
this.taskList[i]()
}
}
_insertTask (task, data, index) {
clearTimeout(this.timer)
this.taskList.splice(index, 0, () => {
this[task](data)
})
this.timer = setTimeout(() => {
this._runTask()
})
return this
}
registerBehave (name, action) {
this['_' + name] = action
this[name] = (data) => {
const fnName = '_' + name
if (/\w+First/.test(fnName)) {
this._insertTask(fnName, data, 0)
} else {
this._addTask(fnName, data)
}
return this
}
return this
}
_hello () {
console.log('Hi I am ' + this.username)
}
}
function LazyMan (name) {
const man = new LazyMan(name)
return man
.registerBehave('sleep', function (time) {
console.log('等待了 ' + time + ' 秒种...')
})
.registerBehave('eat', function (mealName) {
console.log('I am eating ' + mealName)
})
.registerBehave('sleepFirst', function (time) {
console.log('等待了 ' + time + ' 秒种...')
})
}
LazyMan('Pikachu').eat('lunch').sleep(10).sleepFirst(8)
有点长……
但是这样行为就是可以注册的了,以后想加个 gamingFirst
之类的都可以。
用Generator做~
function LazyMan(str = "") {
return new (class {
list = [];
task;
constructor(str) {
this.list.push(`Hi I am ${str}`);
this.task = this.log();
setTimeout(() => this.task.next());
}
sleepFirst = t => {
this.list.splice(1, 0, t);
return this;
};
sleep = t => {
this.list.push(t);
return this;
};
eat = str => {
this.list.push(`I am eating ${str}`);
return this;
};
log = function*() {
for (const val of this.list) {
yield (() => {
if (typeof val !== "number") console.log(val);
setTimeout(() => this.task.next(), (val >> 0) * 1000);
})();
}
};
})(str);
}
LazyMan("Tony")
.eat("lunch")
.eat("dinner")
.sleepFirst(5)
.sleep(10)
.eat("junk food");
class ArrayInherit extends Array {
constructor(options) {
super(options);
this.options=options;
}
push(item) {
super.push(item);
this.options.pushCb(item)
}
}
class LazyMan {
constructor(name) {
this.name = name;
this.sleepQueue = new ArrayInherit({pushCb: function(item) {
setTimeout(() => {
item.cb();
}, item.sleepWait)
}});
this.queueCb = [];
this.sleepWaitTemp = 0;
console.log(`Hi I am ${this.name}`);
}
sleep(sleepWait) {
this.sleepWaitTemp = sleepWait;
return this;
}
sleepFirst(sleepFirstWait) {
const queueCbTemp = this.queueCb;
this.queueCb = []
setTimeout(() => {
queueCbTemp.forEach(cb => {
cb();
})
}, sleepFirstWait)
return this;
}
get hasSleeped() {
return this.sleepWaitTemp > 0;
}
eat(thing) {
function cb() {
console.log(`I am eating ${thing}`);
}
if (this.hasSleeped) {
this.queueCb.forEach(cb => {
cb();
})
this.queueCb = []
this.sleepQueue.push({
sleepWait: this.sleepWaitTemp,
cb: cb.bind(this, thing)
});
} else {
this.queueCb.push(cb.bind(this, thing))
}
return this;
}
}
var a = new LazyMan('Tom');
a.sleep(1000).eat('lunch');
var a = new LazyMan('Tom');
a.eat('lunch').sleep(1000).eat('dinner');
var a = new LazyMan('Tom');
a.eat('lunch').eat('dinner').sleepFirst(2000).sleep(5000).eat('junk food')
其实题目主要考虑的点有以下几个方面:
function LazyMan (name) {
console.log('Hi I am Tony')
return {
loops: [],
tick: null,
eat (something) {
this.wait()
this.loops.push(() => new Promise(resolve => {
resolve(true)
console.log('I am eating ' + something)
}))
return this
},
sleep (time) {
this.wait()
this.loops.push(() => new Promise(resolve => {
setTimeout(() => {
console.log(`等待了${time}秒...`)
resolve(true)
}, time * 1000)
}))
return this
},
sleepFirst (time) {
this.wait()
this.loops.unshift(() => new Promise(resolve => {
setTimeout(() => {
console.log(`等待了${time}秒...`)
resolve(true)
}, time * 1000)
}))
return this
},
wait () {
clearTimeout(this.tick)
this.tick = setTimeout(() => {
this.done()
})
},
done () { // 处理所有的操作
if (this.loops.length > 0) {
this.loops.shift()().then(() => {
this.done()
})
}
},
}
}
function LazyMan (name) {
let obj = Object.create(LazyMan.prototype);
obj.name = name;
obj.taskList = [];
console.log(Hi I am ${name}
);
obj.next();
return obj;
}
LazyMan.prototype.eat = function (message) { this.taskList.push({ type: 'eat', payload: message }); return this; };
LazyMan.prototype.sleep = function (time) { this.taskList.push({ type: 'sleep', payload: time }); return this; };
LazyMan.prototype.sleepFirst = function (time) { this.taskList.unshift({ type: 'sleep', payload: time }); return this; };
LazyMan.prototype.next = function () {
const self = this;
setTimeout(async function () {
let task = null;
while (task = self.taskList.shift()) {
switch (task.type) {
case 'sleep': {
await new Promise((resolve) => setTimeout(resolve, task.payload * 1000));
console.log(等待了${task.payload}秒
);
break;
}
case 'eat': {
console.log(I am eating ${task.payload}
);
break;
}
}
}
}, 0);
}
class LazyManClass {
constructor(name) {
this.taskList = []
this.name = name
console.log(`Hi I am ${name}`)
setTimeout(() => {
this.next()
}, 0)
}
eat (name) {
this.taskList.push(() => {
console.log(`I am eating ${name}`)
this.next()
})
return this
}
sleep (delay) {
this.taskList.push(() => {
setTimeout(() => {
console.log(`等待了${delay}秒...`)
this.next()
}, delay * 1000)
})
return this
}
sleepFirst (delay) {
this.taskList.unshift(() => {
setTimeout(() => {
console.log(`等待了${delay}秒...`)
this.next()
}, delay * 1000)
})
return this
}
next () {
const fn = this.taskList.shift()
fn && fn()
}
}
function LazyMan(name) {
return new LazyManClass(name)
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food')
class Lazy {
constructor(name) {
console.log(`Hi I am ${name}`);
this.task = [];
setTimeout(() => {
this.execQueue(0);
}, 0);
}
execQueue(index) {
var that = this;
if (that.task.length && index < that.task.length) {
that.task[index]().then(res => {
if (res) {
that.execQueue(++index);
}
})
}
}
sleep(s) {
this.task.push(() => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(`等待了${s}秒...`)
resolve(true)
}, s * 1000);
})
})
return this;
}
sleepFirst(s) {
this.task.unshift(() => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(`等待了${s}秒...`)
resolve(true)
}, s * 1000);
})
})
return this;
}
eat(str) {
this.task.push(() => {
return new Promise((resolve, reject) => {
console.log(`I am eating ${str}`);
resolve(true);
});
})
return this;
}
}
function LazyMan(name) {
return new Lazy(name);
}
// LazyMan('Tony').sleep(10).eat('lunch');
// LazyMan('Tony').eat('lunch').sleep(10).eat('dinner');
// LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
LazyMan('Tony'); // Hi I am Tony LazyMan('Tony').sleep(10).eat('lunch'); // Hi I am Tony // 等待了10秒... // I am eating lunch LazyMan('Tony').eat('lunch').sleep(10).eat('dinner'); // Hi I am Tony // I am eating lunch // 等待了10秒... // I am eating diner LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food'); // Hi I am Tony // 等待了5秒... // I am eating lunch // I am eating dinner // 等待了10秒... // I am eating junk food
Answer
class LazyManClass { constructor(name) { this.taskList = []; this.name = name; console.log(`Hi I am ${this.name}`); setTimeout(() => { this.next(); }, 0); } eat (name) { var that = this; var fn = (function (n) { return function () { console.log(`I am eating ${n}`) that.next(); } })(name); this.taskList.push(fn); return this; } sleepFirst (time) { var that = this; var fn = (function (t) { return function () { setTimeout(() => { console.log(`等待了${t}秒...`) that.next(); }, t * 1000); } })(time); this.taskList.unshift(fn); return this; } sleep (time) { var that = this var fn = (function (t) { return function () { setTimeout(() => { console.log(`等待了${t}秒...`) that.next(); }, t * 1000); } })(time); this.taskList.push(fn); return this; } next () { var fn = this.taskList.shift(); fn && fn(); } } function LazyMan(name) { return new LazyManClass(name); } LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(4).eat('junk food');
为什么要写自执行函数自执行函数,感觉有点多余
function lazyMan(name) {
console.log(`Hi I am ${name}`);
const obj = {
task: [],
next() {
// 完成一个任务之后继续完成下面的直到没有任务为止
const task = this.task.shift();
task && task();
},
sleep(second) {
this.task.push(() => {
console.log(`等待${second}秒...`)
setTimeout(() => {
this.next();
}, second * 1000);
})
return this;
},
eat(name) {
this.task.push(() => {
console.log(`I am eating ${name}`)
this.next();
})
return this;
},
sleepFirst(second) {
this.task.unshift(() => {
console.log(`等待${second}秒...`);
setTimeout(() => {
this.next();
}, second * 1000);
})
return this;
}
};
// 先等收集任务
setTimeout(() => {
// 收集好之后开始第一个任务
obj.next();
})
return obj;
}
lazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
class LazyMan {
constructor(name) {
this.tasks = [];
// 启动 tasks,利用 then的 异步原理拿到已经填充好的tasks
Promise.resolve().then(() => {
this.nextTick()
})
console.log(`hi i am ${name}`);
}
sleep(delay) {
this.tasks.push(() => {
setTimeout(() => {
this.nextTick();
}, delay * 1000);
});
return this;
}
sleepFirst(delay) {
// unshift 插队到最前面
this.tasks.unshift(() => {
setTimeout(() => {
this.nextTick();
}, delay * 1000);
});
return this;
}
eat(what) {
this.tasks.push(() => {
console.log(`eating ${what}`);
this.nextTick();
});
return this;
}
nextTick() {
this.tasks.length && this.tasks.shift()();
}
}
class LazyMan {
constructor(name) {
this.name = name;
console.log(`Hi, I am ${name}`)
this.taskQueue = []
setTimeout(() => {
this.start()
})
}
async start() {
for (let task of this.taskQueue) {
await task()
}
}
eat(dinner) {
this.taskQueue.push(() => {
console.log(`I am eating ${dinner}`)
})
return this;
}
wait(time) {
return () => new Promise(resolve => {
setTimeout(() => {
console.log(`waiting ${time} second`)
resolve()
}, time * 1000)
})
}
sleep(time) {
this.taskQueue.push(this.wait(time))
return this;
}
sleepFirst(time) {
this.taskQueue.unshift(this.wait(time))
return this
}
}
// new LazyMan('test1').sleep(2).eat('lunch')
// new LazyMan('test2').eat('lunch').sleep(5).eat('dinner')
new LazyMan('test3').eat('lunch').eat('dinner').sleepFirst(2).sleep(3).eat('junk food')
function LazyMan(str) {
if (this.constructor !== LazyMan) {
return new LazyMan(str)
}
this.willDoThing= []
this.firstDoing = []
this.firstSleep = false
this._init(str)
}
LazyMan.prototype.init = function(str) {
console.log(Hi I am ${str}
);
Promise.resolve().then( => {
this.startDoing()
})
return this
}
LazyMan.prototype.startDoing = async function() {
if (this.firstSleep) {
await this.firstDoing[0]()
this.willDoThing.forEach( async (v) => {await v()} )
}else {
this.willDoThing.forEach( async (v) => {await v()} )
}
}
LazyMan.prototype.sleepFirst = function(time) { this.firstSleep = true this.firstDoing.push(async() => { await sleep(time) console.log('first sleep'+time); }) return this }
LazyMan.prototype.sleep = function(time) { this.willDoThing.push(async() => { await sleep(time) console.log('sleep'+time); }) return this }
function sleep(time) { return new Promise((a,b) => { setTimeout(()=> a() ,time) }) } LazyMan('zz').sleep(1000).sleepFirst(2000)
//备注其他功能就给willdoingThing添加fn就可以了,只是试验了一下两个sleep函数,多了一个判断
function LazyMan(name) {
console.log(`Hi I am ${name}`);
const logArr = [];
const executor = {
_status: 'stoped',
async _actor() {
while (logArr.length) {
const { wait, text } = logArr.shift();
if (wait) await new Promise(resolve => setTimeout(resolve, wait));
console.log(text);
}
this._status = 'stoped';
},
async dispatch() {
if (this._status === 'running') return;
this._status = 'running';
await new Promise(resolve => setTimeout(resolve, 0));
this._actor();
},
};
return {
eat(food) {
logArr.push({
wait: 0,
text: `I am eating ${food}`,
});
executor.dispatch();
return this;
},
sleepFirst(second) {
logArr.unshift({
wait: second * 1000,
text: `等待了 ${second} 秒...`,
});
executor.dispatch();
return this;
},
sleep(second) {
logArr.push({
wait: second * 1000,
text: `等待了 ${second} 秒...`,
});
executor.dispatch();
return this;
},
};
}
function LazyMan(name) {
var o = new Object();
o.name = name;
console.log(`Hi I am ${o.name}`);
o.message = [];
setTimeout(() => {
o.next();
}, 0);
o.eat = function (food) {
var fn = function () {
console.log(`I am eating ${food}`);
o.next();
}
o.message.push(fn);
return o;
}
o.sleepFirst = function (time) {
var fn = function () {
setTimeout(function () {
console.log(`等待了${time}秒...`);
o.next();
}, time * 1000);
}
o.message.unshift(fn);
return o;
}
o.sleep = function (time) {
var fn = function () {
setTimeout(function () {
console.log(`等待了${time}秒...`);
o.next();
}, time * 1000);
}
o.message.push(fn);
return o;
}
o.next = function () {
var fn = o.message.shift();
fn && fn();
}
return o;
}
LazyMan('Jack').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
class LazyManClass {
constructor (name) {
this.name = name
this.task = []
console.log('Hi I am ', name)
setTimeout(() => {
this.next()
}, 0)
}
eat (str) {
this.task.push(() => {
console.log('I am eating ', str)
this.next()
})
return this
}
sleep (n) {
this.task.push(() => {
setTimeout(() => {
console.log('等待了' + n + 's')
this.next()
}, n)
})
return this
}
sleepFirst (n) {
this.task.unshift(() => {
setTimeout(() => {
console.log('等待了' + n + 's')
this.next()
}, n)
})
return this
}
next () {
let fn = this.task.shift()
fn && fn()
}
};
let LazyMan = function (name) {
return new LazyManClass(name)
};
// LazyMan('Tony');
// Hi I am Tony
// LazyMan('Tony').sleep(10).eat('lunch');
// Hi I am Tony
// 等待了10秒...
// I am eating lunch
// LazyMan('Tony').eat('lunch').sleep(10).eat('dinner');
// Hi I am Tony
// I am eating lunch
// 等待了10秒...
// I am eating diner
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
// Hi I am Tony
// 等待了5秒...
// I am eating lunch
// I am eating dinner
// 等待了10秒...
// I am eating junk food
这道题的关键点有如下几个:
@zeroone001 请问为什么每个函数要通过闭包的形式,参考@lvwxx的形式,不需要闭包也能实现,请问使用闭包是出于什么考虑么
class MyClass{
constructor(name){
this.timer=null;
this.taskList=[];
console.log(`Hi I am ${name}`)
}
sleep(time){
this.run(async ()=>{
await new Promise(resolve=>setTimeout(resolve,time*1000))
console.log(`等待了${time}秒...`)
})
return this
}
sleepFirst(time){
this.run(async ()=>{
await new Promise(resolve=>setTimeout(resolve,time*1000))
console.log(`等待了${time}秒...`)
},'unshift')
return this
}
run(fun,act='push'){
if(this.timer)clearTimeout(this.timer);
this.taskList[act](fun)
this.timer=setTimeout(this.next.bind(this));
return this
}
async next(){
let current;
while(current=this.taskList.shift()){
await current()
}
}
eat(name){
this.run(()=>console.log(`I am eating ${name}`))
return this
}
}
function LazyMan(name){
return new MyClass(name)
}
const LazyManClass = class {
constructor(name) {
console.log('Hi I am ' + name)
this.isPendding = false
this.sleepCb = [[]]
this.sleeping = Promise.resolve()
}
get len() {
return this.sleepCb.length
}
sleepFirst(time) {
this.sleep(time)
return this
}
sleep(time) {
if (this.isPendding) {
this.sleepCb[this.len - 1].push(() => this.sleep(time))
} else {
this.sleepCb.push([])
const mySleepCb = this.sleepCb[this.len - 1]
this.sleeping = new Promise(resolve => {
this.isPendding = true
setTimeout(() => {
console.log(`等待了${time}秒...`)
this.isPendding = false
resolve()
}, time * 1000)
})
this.sleeping.then(() => {
mySleepCb.forEach(fun => fun.call(this))
})
}
return this
}
eat(food) {
if (this.isPendding) {
this.sleepCb[this.len - 1].push(() => this.eat(food))
} else {
console.log('Hi I eating ' + food)
}
return this
}
}
const LazyMan = name => new LazyManClass(name)
class LazyManClass {
constructor(name){
this.name = name
this.queue = [] //队列
console.log(`Hi I am ${this.name}`)
setTimeout(() => {
this.nextTask()
}, 0);
}
sleep(time){
let task = () => {
setTimeout(() => {
console.log(`等待了${time}秒...`)
this.nextTask()
}, time*1000);
}
this.queue.push(task)
return this
}
sleepFirst(time){
let task = () => {
setTimeout(() => {
console.log(`等待了${time}秒...`)
this.nextTask()
}, time*1000);
}
this.queue.splice(0, 0, task)
return this
}
eat(food){
const task = () => {
console.log(`I am eating ${food}`)
this.nextTask()
}
this.queue.push(task)
return this
}
//下一任务
nextTask(){
let task = this.queue.shift()
task && task()
}
}
function LazyMan(name){
return new LazyManClass(name)
}
Answer