点击上方蓝字关注前端真好玩,从此前端进阶不再难
干爆前端是笔者新搞的一个仓库,一网打尽前端面试、学习路径、优秀好文、面试资料等各类内容,帮助大家一年内拿到期望的 offer!
其中一部分内容是「每日更新一道大厂原题」,笔者前段时间靠着人脉收集了一波目前最新各个大厂的面试题,绝不是大规模传播的那种,适合有跳槽计划的读者学习。
目前参与人数众多,笔者建了个打卡群,每天都有数十人参与打卡学习,群内学习氛围相当浓厚,如果你也想参与学习的话可以扫描二维码,备注打卡。

这里是仓库地址:https://github.com/KieSun/fucking-frontend。目前内容包括大厂真题、十五万字面试资料及数百岗位的内推信息,内容还在持续更新,欢迎大家 star 关注。
公众号每周会整合真题及答案,以下是今天的内容:
第一题
以下代码输出什么,为什么?
try {
(async function() { a().b().c() })()
} catch (e) {
console.log(`执行出错:${e.message}`)
}
这道题目主要三个考点:
执行一个没有定义的函数会发生什么
在
async
内部发生报错会发生什么try catch
只能捕获同步代码的异常
因此答案就明了了。
因为我们执行了一个未定义的函数,所以会报错 a is not defind
,又因为是在 async
中,所以报错信息会显示 in promise
。最后 try cathch
只能捕获同步代码的抛错,因为是 async
,所以走不到 catch
里面。
如果我们把代码这样改一下就可以了:
try {
await (async function() { a().b().c() })()
} catch (e) {
console.log(`执行出错:${e.message}`)
}
另外说个小知识点,最新的 Chrome 已经支持在全局作用域下使用 await
了。
第二题
以下代码输出什么,为什么?
try {
let a = 0
;(async function() {
a += 1
console.log('inner', a)
throw new Error('123')
// a()
})()
console.log('outer', a)
} catch(e) {
console.warn('Error', e)
}
这道题目是第一题的演化版,更有趣了,当然本质是一样的,我们就当巩固了。
这道题目基础不好的同学容易答错,很容易以为 async
的函数内部代码就是异步的,实际都还是同步的,把代码改成这样大家就明白了:
function a() {
return new Promise(function(resolve, reject) {
a += 1
console.log('inner', a)
throw new Error('123')
})
}
另外发现还有同学疑问为什么 throw
出去的错误被 promise catch
住了,这个我们直接看标准:
标准具体地址[1]
这里也有一个不错的作答[2]
第三题
请按照用例实现代码
// 请使用原生代码实现一个Events模块,可以实现自定义事件的订阅、触发、移除功能
const fn1 = (... args)=>console.log('I want sleep1', ... args)
const fn2 = (... args)=>console.log('I want sleep2', ... args)
const event = new Events();
event.on('sleep', fn1, 1, 2, 3);
event.on('sleep', fn2, 1, 2, 3);
event.fire('sleep', 4, 5, 6);
// I want sleep1 1 2 3 4 5 6
// I want sleep2 1 2 3 4 5 6
event.off('sleep', fn1);
event.once('sleep', () => console.log('I want sleep'));
event.fire('sleep');
// I want sleep2 1 2 3
// I want sleep
event.fire('sleep');
// I want sleep2 1 2 3
这道题目算是一道常考题了且有很多变种,没有一个标准解法,输出正确就行。
但是如果你能用上一些 ES6 的语法以及处理好一些边界问题,面试官对你的评价会更好点。
class Events {
constructor() {
this.events = new Map();
}
addEvent(key, fn, isOnce, ...args) {
const value = this.events.get(key) ? this.events.get(key) : this.events.set(key, new Map()).get(key)
value.set(fn, (...args1) => {
fn(...args, ...args1)
isOnce && this.off(key, fn)
})
}
on(key, fn, ...args) {
if (!fn) {
console.error(`没有传入回调函数`);
return
}
this.addEvent(key, fn, false, ...args)
}
fire(key, ...args) {
if (!this.events.get(key)) {
console.warn(`没有 ${key} 事件`);
return;
}
for (let [, cb] of this.events.get(key).entries()) {
cb(...args);
}
}
off(key, fn) {
if (this.events.get(key)) {
this.events.get(key).delete(fn);
}
}
once(key, fn, ...args) {
this.addEvent(key, fn, true, ...args)
}
}
参考资料
[1]
标准具体地址: https://tc39.es/ecma262/#sec-control-abstraction-objects
[2]这里也有一个不错的作答: https://github.com/KieSun/fucking-frontend/issues/2#issuecomment-793266365
如果觉得不错,素质三连、或者点个「赞」、「在看」都是对笔者莫大的支持,谢谢各位大佬啦~
我的付费社区「前端怎么玩」
在这里你能获得些什么?
我学习的路径,平时看到的好文章、想法、资料、新技术都会整理好分享出来,帮助你更快成长,开阔眼界,拓宽技术栈。
你的疑问,工作上、技术、职业等等无限次提问,不方便暴露隐私还可以匿名提问,我能回答的肯定会聊聊我的想法。
不定期的线上学习活动组织,打卡分享。
一月一期的高质量分享及答疑,包括简历修改、模拟面试等。
一个高质量的微信群。