2024年,龙年大吉吧。裁员,内卷,逆流而上,万字面经梳理
前言
2024年了,互联网的寒意似乎并没有减退,市场行情看起来还是很不友好样子~
身边的朋友都在说道,今年行情很差,苟住要紧;各位也都被动的越来越卷了,上头让你加班时,再也没有那时到点就下班跑路的气魄了😭
耳闻不如一试,投了几家约了面试,试了下水,看看情况如何🤓
准备
虽说,是想试个水看下外面市场情况,但是该准备的还是要准备的,毕竟机会是留给有准备的人,推荐打算面试的同学还是要多准备准备😀
本篇文章不过多叙述如何准备,着重记录目前市场的面试情况
面试记录
简单介绍一下面试背景:
本人19年毕业,普通本科,计算机专业,4年多前端开发经验,目前投的多是一些中小厂(人员500,1000,1万+规模的都有)
根据面试内容,梳理总结了几个方向
JavaScript
TypeScript
- TypeScript的
type
和interface
区别- 说的比较简单,就是一些博客文章里常见的区别,类型别名、类型合并、元祖等
- TypeScript的泛型,常用泛型
- 类比js的函数进行了说明
- 几个内置工具方法
- TypeScript的内置工具方法
- 记不清那么多,就说了几个常见的
Omit
、Pick
、Partial
、Record
、typeof
、keyof
等
- 记不清那么多,就说了几个常见的
- 类型安全
- 说了
readonly
,面试官提了typeof
,总的来说不是很清楚 - TypeScript 类型安全
- 说了
- 实现一个
type Diff<T,S> = ?
泛型,要求返回两个对象的差异(思考Equal
)interface A{ name: string; age:number; } interface B{ name: string; age:number; mobile:number; } // mobile
React
- react16.8前后
class
类组件和hooks
的区别- 说明使用
class
类组件的原因,维护状态实例,存在的问题 - 说明
fiber
架构诞生的历史背景,对已有问题的优化,也就是hooks
诞生的背景
- 说明使用
- 常用hooks
- 主要介绍了常见的
hooks
和对应的使用场景 - 结合
fiber
作进一步的原理说明
- 主要介绍了常见的
- 虚拟DOM / diff算法
- 这俩可以一起分析,虚拟
DOM
的诞生背景和作用 diff
结合虚拟DOM
做更新优化等- 考虑
react
/vue
的diff
算法区别
- 这俩可以一起分析,虚拟
- class类组件
componentDidMount
中进行setState
和hooks中useEffect(()=>{setState()},[])
进行setState
的区别- 说了队列异步更新的原理,这里说
hooks
的useEffect
class
类组件记不清了
- 说了队列异步更新的原理,这里说
- redux的异步中间件实现
- 看过相关源码,忘了。。,说了
saga
的generator
- 补充:理解中间件的实现方式 => 参数注入,主要是把
dispatch
作为参数传入,在适当的时机调用
- 看过相关源码,忘了。。,说了
- react-router如何监听路由(
vue-router
)- 基本原理需要了解,内部实现
- 合成事件介绍
- 围绕
react
结合fiber
控制优化,异步更新分析
- 围绕
- react合成事件是如何对应每个事件的
- useState状态管理的实现
- 主要围绕
fiber
的双缓存说明,以及在hooks
中以链表的数据结构管理(围绕链表顺序结构说明)
- 主要围绕
- umi的插件实现机制
- 没研究过,提到了对webpack的包装以及参数注入
- umi项目下的
.umi
文件的理解- 主要围绕预构建思考了路由的动态生成维护和
dva
数据model
的维护
- 主要围绕预构建思考了路由的动态生成维护和
- dva的内部实现逻辑
- 主要围绕
rudex
、redux-saga
进行了简要说明,generator
的使用
- 主要围绕
- redux的异步中间件实现原理
- redux-thunk
- 异步更好的方案是采用
redux-saga
,其内部使用了generator
函数,可以更好的控制异步操作的执行顺序
- react创建
context
上下文的方式,参数及作用 - redux的顶层
provider
作用及原因
Vue
- vue响应式原理
- 结合
vue
的初始化过程分析Object.defineProperty()
的数据拦截,最好把整个流程说清楚,getter
依赖收集Dep
、Wacther
,setter
触发更新通知等 vue3
的proxy
说明
- 结合
- 描述了vue2和vue3的区别及实现原理、背景、优化等
- vue中如何只让一个对象的第一层为响应式?
- 提到了 Object.freeze() 方法,追问为什么
- vue双向数据绑定原理
- 结合响应式原理分析,compile解析模板指令和变量替换,绑定对应更新函数,理清
Observer
、Compile
和Watcher
三者的关系
- 结合响应式原理分析,compile解析模板指令和变量替换,绑定对应更新函数,理清
- vue如何做到监听数组的
push
等操作方法,缺陷原因- 主要就是
Object.defineProperty()
的问题,以及vue内部对数组方法进行了拦截重写
- 主要就是
- 低代码项目中拖拉拽引出的对于拖拽嵌套实现的一些问题
- 从原生方面考虑
drag
相关事件,主要在于对边界条件的判断和处理上
- 从原生方面考虑
- 如何实现组件缓存(
keep-alive
)- 粗糙的思考:强缓存组件状态(组件仍有挂载、卸载)
- 对虚拟DOM进行缓存处理,不执行相关生命周期钩子(需要结合源码)
- 聊聊keep-alive组件的使用及其实现原理
xx.vue
文件的处理过程,template模板的处理- 一开始以为是在问
createElement
构建虚拟DOM的过程,后来说明是对template字符串内容的处理,主要为正则匹配(标签元素、变量) - 思考模板中的变量是如何更新的
- 聊聊Vue的template编译
- 一开始以为是在问
- vue3的
ref
、reactive
、unref
、toRefs
的作用和区别 - vue作用域插槽 / react中相似插槽的东西
- 默认插槽、具名插槽、作用域插槽
- 延伸思考:react中类似的东西,render props
- vue中对于视图层中使用到的变量
a ? b : c
,如何更好的做到数据的响应式(b和c只会有一个被使用)
微前端
工程化
- Webpack执行过程
- 围绕webpack执行过程分析,初始化参数、加载插件、使用
loader
处理非js相关文件、广播事件等
- 围绕webpack执行过程分析,初始化参数、加载插件、使用
- npm install过程
- 下载到
node_modules
目录下,更新packge.json
文件,并执行安装命令
- 下载到
- 组件库、工具库npm包发布相关配置区别
- Webpack摘要算法配合服务器实现缓存功能(hash)
- loader、plugin简述
- loader是什么,它的参数是什么?
- Webpack模块加载原理
浏览器
网络
算法
- 有效括号,变体(LeetCode 20)
- 删除链表的倒数第n个节点(LeetCode 19)
- 无重复字符的最长子串(LeetCode 3)
手写题
-
节流、防抖
-
深拷贝
-
实现query查询,支持链式调用
点击查看代码详情实现一个 query,支持链式调用,参数是一个数组
query(arr) .where((item) => item.age > 10) .orderBy('age') .groupBy('city') .execute()
-
where方法,参数用法和 [].filter类似
-
orderBy(key,desc) 排序,desc为true时为倒序
-
groupBy(key) 分组,生成二维数组,效果如下
[ [ { name: 'xiao', city: 'hangzhou' }, { name: 'zhang', city: 'hangzhou' }, ], [ { name: 'li', city: 'shanghai' } ] ]
-
execute 方法,只有当该方法执行的时候函数才开始执行
-
-
字符串模板替换
const data = { name: 'banana', date: { year: '2024' } } const str = '这是一个{{name}}, 今年是{{date.year}}年'
-
请求并发控制
点击查看代码详情实现一个 scheduler 函数,满足以下要求: 1. 接收一个参数 max 控制最大并发请求量 2. 执行以下代码依次输出:2、3、1、4 // -----------------mock一些请求 const request1 = () => new Promise((resolve, reject) => { setTimeout(() => { resolve(1); }, 1000); }); const request2 = () => new Promise((resolve, reject) => { setTimeout(() => { resolve(2); }, 500); }); const request3 = () => new Promise((resolve, reject) => { setTimeout(() => { resolve(3); }, 300); }); const request4 = () => new Promise((resolve, reject) => { setTimeout(() => { resolve(4); }, 400); });
输出题
-
react异步更新输出结果
点击查看代码详情class App extends React.Component { constructor() { super(); this.state = { val: 0, }; } componentDidMount() { this.setState({ val: this.state.val + 1 }); console.log('1', this.state.val); this.setState({ val: this.state.val + 1 }); console.log('2', this.state.val); setTimeout(() => { this.setState({ val: this.state.val + 1 }); console.log('3', this.state.val); this.setState({ val: this.state.val + 1 }); console.log('4', this.state.val); }, 0); } render() { return null; } }
-
JS作用域代码输出题
点击查看代码详情var name = "aaa"; const obj = { name: "bbb", fn1: function () { console.log(this.name); }, fn2: () => console.log(this.name), fn3: function () { return function () { console.log(this.name); }; }, fn4: function () { return () => console.log(this.name); } }; obj.fn1(); obj.fn2(); obj.fn3()(); obj.fn4()();
-
异步,宏任务、微任务输出题
点击查看代码详情async function async1() { console.log("async1"); await async2(); console.log("async2 after"); await async3(); console.log("async3 after"); } async function async2() { console.log("async2"); } async function async3() { console.log("async3"); } console.log("start"); async1(); new Promise((resolve) => { console.log("promise"); resolve(); }).then(() => { console.log("promise then"); }); setTimeout(() => { console.log("setTimeout"); }, 0); console.log("end");
-
一些基础代码输出题
点击查看代码详情// 第一题:隐式类型转换 true == 'true' // 第二题:默认值 function fn(a = 'abc') { console.log('a', a) } fn(null) fn(undefined) // 第三题:判断改代码是否会卡死页面 // 1.情况一 function fn() { console.log('abc') setTimeout(fn, 0) } fn() // 2.情况二 function fn() { console.log('abc') setTimeout(fn(), 0) } fn() // 第四题:思考while循环是否可中断 async function fn() { while (true) { console.log('开始输出') await new Promise(() => { console.log('结果') }) console.log('结束输出') } } fn() // 第五题:执行顺序问题 // 1 2**3**2 // 2 new new Fn().getName()
项目问
项目中的功能和细节一定要做到心中有数,面试官会追着问很多细节,一定要真诚!😄
总结
技术面总的来说还算常规,不少都是常见的八股文,好好准备下还是能应对的;
当然也有一些比较犀利的面试官,问的比较刁钻,如果还只是靠背面经就不行了,你一定是有在这个过程中投入学习的,灵活使用,一定要有自己的理解。
项目非常重要,很多问题是在聊项目细节的过程中提及的,建议抽1-2天时间把项目梳理一下,包括业务流程、项目难点等,最好写下来。
对于手写题,有些方面还有待提高,建议对于常见的手写题还是要多写、多练,特别是promise这类,一定要自己手写几遍。
算法题急不来,常规的典型一定要掌握,什么双指针、动态规划、二分查找等等,没事的时候一天刷1-2题,慢慢就积累上来了,这个只靠死记硬背很难学透,在有一定的数量之后才能引起质变,还是要有那种感觉才行,要不然,看到题,脑子里就空空的,怎么解啊。多刷几题,慢慢的脑子里就有一些解题框架和思路了,方可~
尾声
本文梳理了面试中遇到的一些问题,结合之前自己总结过的文章,已经答复了一部分(已贴出链接的),对于剩余的一些问题,后面会持续输出为面试专题进行归纳(本文会持续更新,补全内容贴上专题链接),对于文中有错误的地方,或者有不同想法的同学,欢迎指出~
要说市场行情寒意,还是能感觉到一些的,目前整个前端市场面试人员很多,有的一个职位投递几十个简历都不算多的,中小厂薪资压的还蛮多的,竞争比较多,卡死在HR谈薪环节的不少。有能力的同学可以多试试大厂😅
总的来说,当下环境还是做好自己,有机会多提升下自己的水平,提高竞争力。加油也好,内卷也罢,能不能熬到下一个风口,并有能力抓住机遇,或许每个人都有自己的答案。
后续打算在这个仓库(JS-banana/interview: 面试不完全指北 (github.com))进行维护,欢迎✨star,提建议,一起进步~
转载自:https://juejin.cn/post/7347905312479592511