「前端」字节前端一面
这已经是复活面了,之前一面完直接秒挂,这次至少目前还活着。
先是个人介绍,这个面试官比较直接,在我介绍到第一个项目的时候就开始问问题了,后面就直接开始拷打项目了,没让我接着往下讲。不得不说,这个面试官的风格就是极具侵略性,会对着你的一个失误猛攻,有些人可能会慌,我的经验就是平常心对待,反正我就是个正常人,我又不是超人,犯错是很正常的事情罢了。
- Vue-Router的几种路由方式
- hash模式和history模式
- SPA是什么,和MPA的区别,有什么缺点?怎么优化?
- 单页面应用/切功能不需要跳页面/首屏速度慢/SSR
- 为什么SSR可以优化,别的不可以吗?
- SPA慢是因为渲染需要js参与,SSR通过服务器直接渲染拿到html,从而加速了访问
- SSR是针对SPA做的优化,别的当然也可以,比如CDN/减少静态资源大小/雪碧图/减少CSS和JS对DOM构建的阻塞
- 还有什么优化的释放,比如我首屏不需要的东西可以不可以异步加载?
- 懒加载,Vue-Router 直接在component后面写箭头回调import;React直接用一个lazy包一个import回调
- 你提到了尽可能减少对DOM的阻塞,什么会阻塞DOM构建?
- CSS 和没有 defer/async 标签的 JS
- 向后端发请求的时候,经常会遇到先选一个选项发请求,这个请求可能有一段时间才能相应,然后又选了另一个选项,你怎么保证我的数据是正确的?
- 请求是可以打断的,比如fetch可以通过AbortController中断请求,然后去发最新的请求就行了
- 有了解过他是怎么实现的吗?
- 就是跟拿到timeoutId去clearTiemout类似,拿到一个句柄,就可以给他发信号让他切断
- "
AbortController
的工作原理是通过创建一个控制器和信号 (AbortSignal
) 来实现。你可以将这个信号传递给fetch
请求或其他支持中断的异步操作。当你调用AbortController.abort()
时,传递的AbortSignal
会触发中断信号,导致异步操作立即停止,并通常会抛出一个AbortError
异常。"
- 如果不用 axios,只让你用HTTP Request,你如何实现?
- 用 Promise 封装一下,http request正常返回的时候就resolve,然后有异常就reject
- 看到你移动端布局使用了tailwindCSS,为什么要用这个?
- 写起来比较简单,不用想类名,然后写起来读起来都比较清晰,开发效率会更高
- 没有缺点吗?
- 从性能上,他最坏不会坏过原生的 CSS,加上他本身是一个 css 的预处理器,可以获得很多预处理器带来的性能提升,比如自动移除未使用的类,打包后更小的css文件体积等
- 从人为因素上来讲,tailwindCSS 可能会间接地让部分开发者写很长的classname,从而降低代码的可读性
- 你的布局里用了flex和grid,为什么用这些?
- grid 主要用来实现一些异形卡片布局,比如我可能要12,21,2*2的卡片,这样的布局用grid写起来会非常方便
- flex 作为现代的弹性布局方式,在对齐、多列布局方面非常方便
- 配合css的媒体查询去做移动端的响应式布局
- 有没有了解过其他的响应式布局方式?
- 还可以通过UA来判断用户设备,然后返回不同的布局
- 那这个布局是如何转换的?
- 聊了一些vw、vh、rem之类的方式
- 下面是无聊的八股部分
- css如何局中一个元素
- 定位/浮动/BFC
- 为什么从今年的1月份到现在做了这么多项目?
- 因为要学习,要找工作😅
- CDN解决什么问题?
- 静态资源加载缓慢
- 浏览器渲染网页的过程
- 八股复读
- js的代码输出题,常规的宏任务/微任务事件循环考察
- async await 背后的具体实现有了解过吗?
- 就是Promise的语法糖,可以等价的转化为Promise.then之类的,但是面试官对这个答案不是很满意,说你这个是用法,不是原理
- 我猜他想听:
async
函数是返回一个Promise
的函数。即使函数内部没有显式地返回Promise
,也会自动将返回值包装成Promise
;await
会暂停async
函数的执行,直到Promise
被解析(即变为成功或失败),然后恢复函数的执行,并返回Promise
的结果。如果Promise
被拒绝,await
表达式会抛出异常,这可以通过try/catch
块来捕获。
- 手撕:最长公共前缀
- 继续八股:
- 常见的数据结构/特性/用法/场景
- js里的数据类型/复杂类型和简单类型的区别
- 值传递和引用传递的区别
- 事件冒泡/可以用这个机制实现什么?(事件代理)
- 看你这里手写了一个进度条,如果需要你将其封装成一个通用的组件,你怎么写?
- 一开始说了自定义hooks,后来聊下来发现其实介绍一个prop作为百分比然后更新就行了
- 然后面试官就开始拷打,说你为什么一上来就说自定义hooks?
- 我就花了不到3s思考这个问题,难免有不周到的地方,实际开发过程中肯定有更充足的思考时间(这个面试官问的非常有侵略性,但我还是努力在反驳,我觉得几秒钟的考虑时间有点失误也很正常吧)
- 继续延伸,如果你想让这个组件支持自定义样式,你该如何实现?
- 拿一个属性去接受className就行了
- 然后又开始跟我纠结为什么不是style而是className,我怎么知道用户一定就用tailwindCSS?
- 反正你拿两个属性都接受不就完了吗,支持tailwindCSS是个额外的feature,大不了你不用呗
- 当你封装一个组件的时候,最重要的是什么?
- 高内聚,低耦合(面试官觉得太虚了,让我细说)根据Vue官方文档的推荐,你的组件应该提供详细的props的类型定义甚至validator,因为你的props的定义其实就是你的组件的使用文档
- 你的项目上提了一些性能指标,都是什么意思,什么问题会导致某个指标高,如何优化?
- 八股复读
- 那这些优化你有实现过吗?
- 我写的这些网页都比较简单,所以没有做过具体的性能优化
- 那你为什么要写这个性能指标?
- 因为我care性能
- 你care性能为什么不去优化他,那你关心他干嘛?
- 因为我不去优化是因为我认为他足够好,而不是我不知道性能可以优化
- 你如何做性能分析?
- lighthouse/performace
- JS 里捕获异常的方式有哪些呢?
- try/catch Promise.catch之类的
- 你说的都是局部的,我不可能每个地方都try/catch吧
- 我一开始说的高阶组件,面试官又问说那我不用框架呢
- 那你最上层try/catch呗
- 可以用一些全局异常捕获的api,比如window.onerror, window.onunhandledrejection
- 推荐了《高级程序设计》这本书