编程类题目

Q1

实现一个LazyMan,可以按照以下方式调用

(请写出实现代码或详细思路)
functon 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方法可以链式调用sleep sleepFirst eat方法。

说明LazyMan 和 这3个方法的执行结果都返回一个包含这3个方法的对象。

所以我定义一个class类(_LazyMan),在调用LazyMan的时候返回使用这个类创建的实例。

然后,sleep 和 sleepFirst 方法会延时打印内容,所以会用到setTimeout方法。

而其他方法的打印,会根据使用位置,在sleep[First]方法执行完后再执行。

所以要用到await,强制同步执行。

setTimeout方法本身是同步执行的,它的回调是延迟执行的,所以需要用Promise包裹setTimeout,使await能等待setTimeout执行完再执行后面的代码。

LazyMan单独执行会打印内容,说明_LazyMan的构造函数中有打印任务。

最后关键的是,sleepFirst会使构造函数的默认打印延后。

所以需要创建一个队列,在调用方法时,向队列添加任务,并在最终执行这个队列的任务。

首先,每个方法中的内容包括:添加任务到队列,通知队列执行。

目前每个方法执行完,都会执行队列的任务。

所以执行队列这个操作,要放到当前执行栈外面(通过setTimeout),保证在每个方法执行结束后,才执行队列的任务。

并且在添加任务时,要清除上一次的setTimeout,避免重复执行队列。

代码如下

class _LazyMan {
  constructor(name) {
    // 创建一个任务队列
    this.taskQueue = []
    // 存储一个计时器,用于重置
    // 计时器的任务是执行队列中的任务
    this.runTimer = null

    this.say(name)
  }

  // 创建一个控制台,重置计时器,启动计时器
  _run() {
    // 重置计时器
    if (this.runTimer) {
      clearTimeout(this.runTimer)
    }
    // 启动计时器
    this.runTimer = setTimeout(async () => {
      // 同步执行队列任务
      // 注意不要使用 forEach + await方式
      for (let fn of this.taskQueue) {
        await fn()
      }
    })
    // 返回实例,保证链式调用
    return this
  }
  
  say(name) {
    this.taskQueue.push(async () => {
      console.log(`Hi! This is ${name}!`)
    })
    // 通知控制台
    return this._run()
  }

  eat(meal) {
    this.taskQueue.push(async () => {
      console.log(`Eat ${meal} ~`)
    })
    return this._run()
  }

  sleep(delay) {
    this.taskQueue.push(this._timeout(delay))
    return this._run()
  }

  sleepFirst(delay) {
    // 向前添加任务
    this.taskQueue.unshift(this._timeout(delay))
    return this._run()
  }

  // 创建一个延时的 sleep
  _timeout(delay) {
    return async () => {
      await new Promise(resolve => {
        setTimeout(() => {
          console.log(`Wake up after ${delay}`)
          resolve()
        }, delay * 1e3)
      })
    }
  }
}

const LazyMan = function (name) {
  return new _LazyMan(name)
}

LazyMan('Hank')
// LazyMan('Hank').sleep(10).eat('dinner')
// LazyMan('Hank').eat('dinner').eat('supper')
// LazyMan('Hank').sleepFirst(5).eat('supper')


Q2 已知如下对象,请基于es6的proxy方法设计一个属性拦截读取操作的例子

要求实现去访问目标对象example中不存在的属性时,抛出错误:Property “$(property)” does not exist

// 案例代码
const man = {
  name: 'jscoder',
  age: 22
}
//补全代码
const proxy = new Proxy(...)
proxy.name // "jscoder"
proxy.age // 22
proxy.location // Property "$(property)" does not exist

回答:

// 案例代码
const man = {
  name: 'jscoder',
  age: 22
}
//补全代码
const proxy = new Proxy(man, {
  get(obj, key) {
    if (man[key] === undefined) {
      throw Error(`Property “${key}” does not exist`)
    } else {
      return Reflect.get(obj, key)
    }
    // 其他判断方法
    // if (Reflect.has(obj, key)){}
    // if (key in obj){/*会一直查找到原型*/}
  }
})
const { log } = console
log(proxy.name) // "jscoder"
log(proxy.age) // 22
log(proxy.location) // Property "$(property)" does not exist

Q3 红灯三秒亮一次, 绿灯一秒亮一次, 黄灯2秒亮一次

实现一个函数,如何让三个灯不断交替重复亮灯? (用Promise实现) 三个亮灯函数已经存在:

function red() {
  console.log('red')
} // 3秒
function green() {
  console.log('green')
} // 1秒
function yellow() {
  console.log('yellow')
} // 2秒

回答:

function red() {
  console.log('red')
} // 3秒
function green() {
  console.log('green')
} // 1秒
function yellow() {
  console.log('yellow')
} // 2秒

function light(fn, delay) {
  return new Promise(resolve => {
    setTimeout(() => {
      fn()
      resolve()
    }, delay * 1000)
  })
}
function begin() {
  Promise.resolve()
    .then(() => {
    return light(red, 3)
  })
    .then(() => {
    return light(green, 1)
  })
    .then(() => {
    return light(yellow, 2)
  })
    .then(() => {
    begin()
  })
}
begin()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值