Posted in

经典回溯,从一个老面试题(LazyMan)中学到的知识_AI阅读总结 — 包阅AI

包阅导读总结

1. `LazyMan`、`面试题`、`链式调用`、`执行顺序`、`任务队列`

2. 本文从一道关于`LazyMan`函数的面试题入手,讲述了实现该函数的过程,包括不同方法的功能及实现思路,最终通过任务队列控制执行顺序完成题目,认为此题考点多有难度。

3.

– 人们常因信息、欲望、能力等因素而不安,低层次动物心灵容纳信息简单。

– 介绍`LazyMan`面试题

– 描述题目,如`LazyMan(‘Hank’)`等不同调用方式及对应输出。

– 奠定`LazyMan`的基调。

– 实现`LazyMan`函数

– 实现`LazyMan(‘Hank’)`,直接打印参数值。

– 实现`sleep(10)`和`eat(‘lunch’)`,用死循环等待实现`sleep`。

– 完善`eat`函数,根据参数打印不同结果。

– 实现`sleepFirst`函数,通过任务队列控制执行顺序。

– 总结完成题目,称赞此题有难度且考点多。

思维导图:

文章地址:https://juejin.cn/post/7380221367823712265

文章来源:juejin.cn

作者:陪我去看海

发布时间:2024/6/14 15:15

语言:中文

总字数:2175字

预计阅读时间:9分钟

评分:88分

标签:前端,面试,JavaScript


以下为原文内容

本内容来源于用户推荐转载,旨在分享知识与观点,如有侵权请联系删除 联系邮箱 media@ilingban.com

人们因能感知太多信息而感到心神不宁,或因产生过多欲望而痛苦不堪,又或因担忧能力不足而滋生焦虑,无论顺境或是逆境都不得安生。就像今天的我们,虽衣食无忧,却总是苦于无法摆脱手机的干扰,无法获取让人羡慕的技能,无法拥有想要的生活,等等。低层次的动物是没有这种烦恼的,它们的心灵只容纳环境中确实存在的、与它们切身相关的、靠直觉判断的信息——饥饿的狮子只注意能帮助它猎到羚羊的信息,吃饱的狮子的注意力则集中在温暖的阳光上…… ——《认知觉醒》

前言

“旧游如梦,重逢却是初见”,这句话很好的描述了再看见这个面试题的感觉,最开始知道这道题的时候,它只是道题,再看见时,它好像变成了很多知识点,这也是一种进步的吧。

题目

可能有些人不知道这道题目,所以有必要描述一下题目,这是一道经典题目

> LazyMan('Hank')你好,我是 Hank> LazyMan('Hank').sleep(10).eat('lunch')你好,我是 Hank(等10秒...)我醒了,我刚睡了 10 秒吃午餐> LazyMan('Hank').eat('lunch').eat('supper')你好,我是 Hank吃午餐吃晚餐> LazyMan('Hank').sleepFirst(5).eat('supper')(沉默5秒)我醒了,我刚刚睡了 5 秒你好,我是 Hank吃晚餐
  • 需要实现 LazayMan 函数,函数接收一个参数
  • 实现链式调用
  • 实现sleep, eat, sleepFirst方法,且执行时机要与上述匹配

知道上述情况后,大致可以奠定LazyMan的基调

const LazyMan = (name) => {		return {			sleep(){},				eat(){},				sleepFirst(){}					}}  LazyMan("Hank")

清楚题目后,我们开始来实现吧,如果可以,我建议你可以自己先想一想!

实现 LazyMan(‘Hank’)

从这里第一个打印来看,非常简单,只需要将这个参数值在控制台打印出即可

代码实现

const LazyMan = (name) => {	console.log(`你好,我是${name}`)		return {			sleep(){},				eat(){},				sleepFirst(){}			}}  LazyMan("Hank")

这样就可以得到第一个打印结果:

Pasted image 20240614220315.png第一步实现非常简单,对吧,接下来继续实现下一个

实现sleep(10)和eat(‘lunch’)

首先看到LazyMan('Hank').sleep(10).eat('lunch')打印结果

你好,我是 Hank(等10秒...)我醒了,我刚睡了 10 秒吃午餐
  • sleep函数的执行时机是按照链式调用顺序执行,且sleep的作用是等待n秒后,再执行后续调用
  • eat函数就是根据参数打印是吃午餐,还是吃晚餐还是…清楚这些后,我们开始在原来的代码上添加修改代码,以达到目的,既然 sleep 是等待n秒后执行其他函数,那我直接死循环等待即可

代码实现:

const LazyMan = (name) => {	console.log(`你好,我是${name}`)		const lazyMan = {			sleep(second){					let startTime = Date.now()						while (Date.now() - startTime < 10000) { } 						console.log(`我醒了,刚刚睡了${second}秒`)						return lazyMan 				},				eat(type){					console.log("吃午餐")				},				sleepFirst(){}		}		return lazyMan}LazyMan("Hank").sleep(10).eat("lunch")

完工,这样我们也达到了这个调用的打印顺序要求了,查看结果:

Pasted image 20240614222610.png接下来继续实现下一个

实现eat函数

我们先看到调用方式LazyMan('Hank').eat('lunch').eat('supper'),在看打印结果

你好,我是 Hank吃午餐吃晚餐
  • eat链式调用
  • eat根据参数不同,打印出不同文字很巧,链式调用就是直接返回一个对象即可,我们已经完成了,剩下就是根据不同参数,打印不同结果了

代码实现:

const LazyMan = (name) => {	console.log(`你好,我是${name}`)		const eatInfoMap = {			'lunch': "吃午餐",				'supper': "吃晚餐"		}		const lazyMan = {			sleep(second){					let startTime = Date.now()						while (Date.now() - startTime < 10000) { } 						console.log(`我醒了,刚刚睡了${second}秒`)						return lazyMan 				},				eat(type){					console.log(eatInfoMap[type])						return lazyMan				},				sleepFirst(){}		}		return lazyMan}LazyMan('Hank').eat('lunch').eat('supper')

这样似乎就满足了当前需求,查看打印结果:

Pasted image 20240614223408.png实现了这个以后,我们继续实现

实现sleepFirst函数

看到调用方式LazyMan('Hank').sleepFirst(5).eat('supper'),再看打印结果

(沉默5秒)我醒了,我刚刚睡了 5 秒你好,我是 Hank吃晚餐

这时候发现,如果继续采用之前的方式,好像永远也无法实现这个了,有点难受,这说明前面的想法都是错误的了再分析一下,sleepFirst可以改变链式调用的执行顺序,所以代码执行的顺序,需要我们进行控制,关于控制顺序的方式,刚好有执行队列呀,我们只需要把需要先执行的推送到执行队列最前方不就好了,然后考虑到有等待,可以让每一个执行队列的第一个任务执行完成后,再提醒后续执行,这样不就解决了嘛,那就试试吧!

删除之前代码,改变思路,使用一个队列来控制执行顺序

代码实现:

const LazyMan = (name) => {	const eatInfoMap = {			'lunch': "吃午餐",				'supper': "吃晚餐"		}			const queue = [] 		const helloTask = () => {			console.log(`你好,我是${name}`);				next()		}		queue.push(helloTask) 		  		const next = () => {			const firstFn = queue.shift();				firstFn?.()		}		  		const lazyMan = {			sleep(s){					const task = () => {							setTimeout(() => {									console.log(`我醒了,我刚睡了 ${s} 秒`)										next()							}, s * 1000)						}						queue.push(task)						return lazyMan				},			eat(type){					const task = () => {							console.log(eatInfoMap[type])								next()						}						queue.push(task)						return lazyMan				},			sleepFirst(s){								const task = () => {							setTimeout(() => {									console.log(`我醒了,我刚刚睡了 ${s} 秒`)										next()								}, s * 1000)						}						queue.unshift(task)						return lazyMan				}		}	  			setTimeout(() => next())		return lazyMan}LazyMan('Hank').sleepFirst(5).eat('supper')
  • 使用了任务队列,让执行顺序变成可控的
  • 所有的链式调用,先收集任务,按照函数效果插队,到对应位置
  • 使用 next 作为媒介,当自己执行完成,让后续继续执行

查看结果:

Pasted image 20240614230644.png

至此,就完成了这道题目,我真的觉得相出这道题目的人是天才,哈哈哈,考点挺多的,如果之前没接触,还是很难写出来。