Google 的 JavaScript 面试题

2025-05-24

Google 的 JavaScript 面试题

大家好,欢迎回到“代码评审”系列,这是一个每周在 Dev.to 独家发布的编程面试挑战和职业相关内容系列。我叫伊丽莎白,从事软件工程师工作已有 4 年多了。我热衷于分享我的知识,以及在面试中脱颖而出或提升编程技能的最佳技巧和窍门。如果您想获得更多类似的内容和挑战,请点击此处订阅 Coderbyte 时事通讯。单口相声系列就到这里——让我们开始挑战吧!

挑战

编写一个类,EventEmitter它有三个方法:on、、emitremoveListener

  • on("eventName", callbackFn)- 一个接受eventName和 的函数,应该保存在发出callbackFn事件时要调用的callbackFn 。eventName
  • emit("eventName", data)- 一个接受eventNamedata对象的函数,应该调用callbackFn与该事件关联的 s 并向它们传递data对象。
  • removeListener("eventName", callbackFn)- 一个接受eventName和的函数,应该从事件中callbackFn删除它。callbackFn

例如:


let superbowl = new EventEmitter()

const cheer = function (eventData) {
  console.log('RAAAAAHHHH!!!! Go ' + eventData.scoringTeam)
}

const jeer = function (eventData) {
  console.log('BOOOOOO ' + eventData.scoringTeam)
}

superbowl.on('touchdown', cheer)
superbowl.on('touchdown', jeer)

superbowl.emit('touchdown', { scoringTeam: 'Patriots' }) // Both cheer and jeer should have been called with data

superbowl.removeListener('touchdown', jeer)

superbowl.emit('touchdown', { scoringTeam: 'Seahawks' }); // Only cheer should have been called

解决方案:

这是使用 ES6 类的绝佳机会。如果您以前没用过,可以在这里查看它们的语法。我们可以从类的基本结构开始,并用一个用于跟踪事件的EventEmitter对象来初始化它。events

class EventEmitter {
  constructor () {
    this.events = {}
  }
}

接下来我们可以开始编写方法了。首先是on。代码如下:

on (eventName, callbackFn) {
  if (!this.events[eventName])  {
    this.events[eventName] = []
  }
  this.events[eventName].push(callbackFn)
}

因为函数是JavaScript 中的第一类对象eventName,这基本上意味着它们可以存储在变量、对象或数组中,所以我们可以将回调函数推送到存储在事件对象中的键的数组中。

发射

现在,开始我们的emit功能。

  emit (eventName, eventData) {
    if (!this.events[eventName]) return
    this.events[eventName].forEach(fn => fn(eventData))  
  }

此解决方案利用了 JavaScript 中所谓的“闭包”。如果你在面试中使用 JavaScript 编写代码,理解闭包至关重要。闭包的本质是函数引用了其周围的状态或词法环境。你也可以将其理解为一个允许你在内部函数中访问外部函数作用域的闭包。使用全局变量就是一个很棒的闭包简单示例。

这是使用闭包来跟踪函数被调用次数的另一个很好的例子。

function tracker (fn) {
  let numTimesCalled = 0
  return function () {
    numTimesCalled++
    console.log('I was called', numTimesCalled)
    return fn()
  }
}

function hello () {
  console.log('hello')
}

const trackedHello = tracker(hello)

返回的内部函数tracker覆盖了变量 numTimesCalled,并在trackedHello函数的整个生命周期内保持对它的引用。很酷吧?

删除监听器

这种removeListener方法可能是三种方法中最简单的。这里有一个解决方案:

removeListener (eventName, callbackFn) {
  const idx = this.events[eventName].indexOf(callbackFn)
  if (idx === -1) return
  this.events[eventName].splice(idx, 1)
}

课程就到这里!双关语:)看看自己能否实现语言本身的方法是备战面试的好方法。下周见!

文章来源:https://dev.to/coderbyte/a-javascript-interview-question-asked-at-google-19f1
PREV
如何打造一个能给未来雇主留下深刻印象的副业
NEXT
10 天内构建 10 个 CSS 项目:项目 5