本文由 简悦 SimpRead 转码, 原文地址 mp.weixin.qq.com
今天给大家分享一个大厂的面经——网易灵犀
题目
一面
1、聊项目
2、webpack 和 rollup 的区别,打包出来的产物有什么区别?
3、postcss 的原理
4、webpack babel vue 都用到了 AST,你是怎么理解 AST 的?
5、如何提高 webpack 的构建速度?
6、用到了 vite 了么?为什么会快?
7、npm 打包时需要注意哪些?如何利用 webpack 来更好的构建?
8、如何在 vue 项目中实现按需加载?
9、webpack 怎么优化前端性能
10、是否写过 loader 和 plugin,大概思路是什么样的?
11、实现 Array 中的 reduce 方法?
二面
1、聊简历,聊项目
2、vue 中的 nexttick 的原理
3、vue 的响应式原理
4、小程序的架构
5、小程序如何跟 native 层通信的
6、算法题
要求:
求字符串公共前缀,例如 ['abcaaa', 'abcddd', 'abcadad'] ==> 'abc'7、算法题
要求:
// 区间合并:// 以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。// 请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。 // 示例 1:// 输入:intervals = [[1,3],[2,6],[8,10],[15,18]]// 输出:[[1,6],[8,10],[15,18]]// 解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6]. // 示例 2:// 输入:intervals = [[1,4],[4,5]]// 输出:[[1,5]]// 解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。解答
一面
1、聊项目
略
2、webpack 和 rollup 的区别,打包出来的产物有什么区别?
webpack:代码拆分,按需加载,适用于应用的打包,webpack2 后已支持
tree-shakingrollup:所有资源打包到同一个地方,一次性加载,适用于库的打包,支持
tree-shaking
3、postcss 的原理?
第一步:调用 postcss 相关的 loader 并传入参数
第二步:将 css 文件转成 AST
第三步:根据第一步的参数,对 AST 进行修改枝叶
第四步:将修改后的 AST 转化为正常代码
第五步:输出代码,交给下一个 loader 处理
4、webpack babel vue 都用到了 AST,你是怎么理解 AST 的?
现在的很多工具,例如 webpack、vite、eslint、babel 等等都离不开一个东西——AST。AST 是正常代码,使用工具,根据不用的代码节点类型,转化成的一个 JSON 格式的数据
5、如何提高 webpack 的构建速度?
后面会单独出一篇文章
6、用到了 vite 了么?为什么会快?
1、esbuild 预构建依赖:代码分为
依赖和源码,依赖就是那些 npm 包,一般不会变,缓存起来;源码是会频繁更改的那一部分代码2、利用浏览器可以运行
ES Module,将代码转成ES Module后交给浏览器,把压力放在浏览器那边,从而提高项目启动速度3、按需加载:浏览器根据
ES Module去使用 http 请求,按需加载所需页面4、利用协商缓存,缓存文件,无变化的文件不需要重新加载
7、npm 打包时需要注意哪些?如何利用 webpack 来更好的构建?
后面会单独出一篇文章
8、如何在 vue 项目中实现按需加载?
箭头函数 + import
9、webpack 怎么优化前端性能?
后面会单独出一篇文章
10、是否写过 loader 和 plugin,大概思路是什么样的?
loader loader 的作用是用来处理非js文件,它是一个函数,实现原理是:将所需处理的文件内容使用相应的转换插件转成AST(抽象语法树),然后按照 loader 规则对于这个 AST 进行处理,处理之后再转成原本的内容格式,然后输出,达到了处理内容的效果
plugin plugin 的作用是拓展 webpack 的打包功能。它是一个类,使用方式是 new Plugin(option),这个类内部有一个apply方法,打包时会执行这个方法,且这个apply方法接收的参数中有一个plugin方法,此方法中有许多钩子函数,使用这些钩子函数可以在不同的打包阶段做一些事,例如修改文件,新增文件,删除文件等等
11、实现 Array 中的 reduce 方法?
Array.prototype.sx_reduce = function(cb, ...args) { let pre, start = 0 if (args.length) { pre = args[0] } else { pre = this[0] start = 1 } for (let i = start; i < this.length; i++) { pre = cb(pre, this[i], i, this) } return pre}二面
1、聊简历,聊项目
略
2、vue 中的 nexttick 的原理?
nexttick 首选微任务,然后才是宏任务。内部设置一个回调队列,将渲染 watcher 还有用户自定义的 nexttick 事件放到这个队列里,并异步执行循环这个队列,达到异步更新
3、vue 的响应式原理
使用 Object.defineProperty 拦截对象属性的 get 和 set,再通过 dep 收集依赖的 Watcher,当属性更新时触发 set,并触发 notify 函数通知 dep 中的 watcher 进行更新。watcher 分为渲染 watcher、用户 watcher、计算 watcher。
缺点是:
1、没有对数组进行拦截 get 和 set,而是修改原型方法。
2、没有兼顾对象新增属性的响应式处理
3、费性能,毕竟是通过递归拦截
4、小程序的架构
不懂
5、小程序如何跟 native 层通信的
不懂
6、算法题
要求:
求字符串公共前缀,例如 ['abcaaa', 'abcddd', 'abcadad'] ==> 'abc'解题:
var longestCommonPrefix = function (strs) { if (!strs.length) return '' if (strs.length === 1) return strs[0] const start = strs[0] let prefix = '', pre = '' for (let i = 0; i < start.length; i++) { prefix += start[i] if (strs.some(str => str.indexOf(prefix) !== 0)) return pre pre = prefix } return pre};7、算法题
要求:
// 区间合并:// 以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。// 请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。 // 示例 1:// 输入:intervals = [[1,3],[2,6],[8,10],[15,18]]// 输出:[[1,6],[8,10],[15,18]]// 解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6]. // 示例 2:// 输入:intervals = [[1,4],[4,5]]// 输出:[[1,5]]// 解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。解答:
const merge = function(intervals) { if (intervals.length === 1) return intervals intervals.sort((a, b) => a[0] - b[0]) const res = [] let i = 0, j = 1 while(j < intervals.length) { const iArr = intervals[i] const jArr = intervals[j] if (iArr[1] >= jArr[0]) { intervals[i] = [Math.min(iArr[0], jArr[0]), Math.max(iArr[1], jArr[1])] j++ if (j === intervals.length) res.push(intervals[i]) } else { res.push(iArr) i = j++ if (j === intervals.length) res.push(jArr) } } return res};8、算法题
要求:
// 仿模板字符串处理功能,// 如 "Title: ${ title }, MainArtist: ${ artist[0] }, Album: ${ album.name }",// {// title: '珊湖海',// artist: ['周杰伦', '梁心颐'], // album: {// publishTime: '2006-11-1',// name: '十一月的萧邦'// }// };