CVTE
5月14日
面试部门:希沃未来教育某部门(广州)
一面
面试形式:电话面
面试时常:1小时6分钟
面试感悟:面试官人很和善,基本全程都在"嗯",也会和你开玩笑,然后我答不出来的时候他也会说:"嗯,没关系,问题不大"。不过可能是因为自己在某些问题上回答的太繁重了,导致经常被面试官打断(大概有2,3次吧),所以大家在面试的时候也要抓重点回答不要偏离问题的方向。
离职原因
新的一份工作你主要看中的是什么?
平台、团队、薪资、地域
先说一下你的期望薪资吧
你为什么觉得你这次跳槽能有这么大的工资涨幅
我是从这几个角度来分析的:
- 自己离职前本来应该还有一次加薪机会的,但是走了,所以我认为这次跳槽的薪资幅度也不算高
- 对比于相同工作年限的同行来说在技术上可能会稍微强一些
- 自己的社区影响力,喜欢写博客
如果给不到期望薪资你会怎么办
薪资只是我找工作的其中一个比较项,回到我最原始的想法,我更在意的是平台和团队。
说一下你们项目动态表单的实现
你遍历JSON树的具体过程
webpack构建流程
(当时是按欧巴的总结答的:「吐血整理」再来一打Webpack面试题(持续更新) (opens new window))
初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数
开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译
确定入口:根据配置中的 entry 找出所有的入口文件
编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理
完成模块编译:在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系
输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会
输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统
webpack插件原理
webpack 在编译代码过程中,会触发一系列 Tapable 钩子事件,插件所做的,就是找到相应的钩子,往上面挂上自己的任务,也就是注册事件,这样,当 webpack 构建的时候,插件注册的事件就会随着钩子的触发而执行了。
webpack在配置插件的时候是一个数组那它有顺序吗
当时我回答的是:这个可能要从webpack插件设计者的角度来看吧,因为webpack插件它是可以指定在哪个生命周期来做某些处理的,所以我认为它主要是和设计时的调用时机有关,而和定义时数组里的顺序无关;但是loader我知道它是有执行顺序的,一般是从右到左,从下到上,但是也可以用一个叫做enforce的属性去改变执行顺序。
有用过哪些插件做项目的分析吗
当时答的:
webpack-dashboard:可以更友好的展示相关打包信息。
speed-measure-webpack-plugin:简称 SMP,分析出 Webpack 打包过程中 Loader 和 Plugin 的耗时,有助于找到构建过程中的性能瓶颈。
size-plugin:监控资源体积变化,尽早发现问题
webpack-bundle-analyzer:分析打包后整个项目中的体积结构,既可以看到项目中用到的所有第三方包,又能看到各个模块在整个项目中的占比。
有做过哪些webpack优化吗
当时答的:
- 使用
purgecss-webpack-plugin和glob插件去除无用样式(glob插件可以可以同步查找目录下的任意文件夹下的任意文件):
new PurgecssWebpackPlugin({
// paths表示指定要去解析的文件名数组路径
// Purgecss会去解析这些文件然后把无用的样式移除
paths: glob.sync('./src/**/*', {nodir: true})
// glob.sync同步查找src目录下的任意文件夹下的任意文件
// 返回一个数组,如['真实路径/src/css/style.css','真实路径/src/index.js',...]
})
- 文件解析优化:
babel-loader编译慢,可以通过配置exclude来去除一些不需要编译的文件夹,还可以通过设置cacheDirectory开启缓存,转译的结果会被缓存到文件系统中- 文件解析优化:通过配置
resolve选项中的alias、extensions、modules来实现。alias创建import或者require的别名;加快webpack查找速度。extensions自动解析确定的扩展;modules解析模块时应该搜索的目录,通常建议使用绝对路径,避免层层查找祖先目录。
- 还有的话,从
webpack-merge提取一些公共的配置项
有自己写过插件吗
必问...
让你从零开始构建一个webpack项目你可以吗
实不相瞒的告诉您,我之前有写过webpack相关的这一部分教程,包括从零开始搭建,然后再到基本的loader的使用,比如style- loader、css-loader、raw-loader等,然后到一些基本的插件的使用,比如html-webpack- plugin、clean-webpack-plugin,以及像webpack-dev-server...
面试官:"好了好了,我大概清楚了,OK,这个问题我们过吧"
从输入URL到页面呈现的过程
必问...
为什么TCP要三次握手而不是两次
(这个大家应该都清楚)
为了保证双方都有发送和接收的能力,如果只有两次握手的话就只能保证发送方,一般就是我们的客户端有发送的能力,但是并不能保证它有接收的能力,所以必须是三次。
HTTP和TCP的区别
当时的答案:
HTTP的责任是去定义数据,在两台计算机相互传递信息时,HTTP规定了每段数据以什么形式表达才是能够被另外一台计算机理解。
而TCP所要规定的是数据应该怎么传输才能稳定且高效的传递与计算机之间。
你们项目一般是如何做缓存的
当时答的很乱...就提到了一些Expires以及cache-control等等。
- 对于一些没有指纹信息的资源,例如
index.html可以使用Cache-Control: no-cache开启协商缓存 - 对于带有指纹信息的资源,一般会使用splitChunksPlugin进行代码分割,来保证造成最小范围的缓存失效,再设置
Cache-Control: max-age=3153600
(答的时候,由于想给自己争取更多的思考时间,就佯装咳嗽,面试官问你还好吧,要不要喝口水😂)
什么情况会阻塞页面的加载
提到了script加载的时候会阻塞页面。JS属于单线程,当我们在加载script标签内容的时候,渲染(GUI)线程会被暂停,因为script标签里可能会操作DOM的,所以如果你加载script标签又同时渲染页面肯定就冲突了,因此说渲染线程(GUI)和js引擎线程互斥。
然后我还想说一下引用CSS的时候使用@import也会,然后就被面试官打断了。
script放在body头部就一定会阻塞吗
没想出来,然后反问了他是不是不操作DOM就不会?
面试官:呵呵呵,没事,你等会去了解一下
但后面有了解到,面试官想问的可能是async和defer吧:
正常模式
这种情况下 JS 会阻塞浏览器,浏览器必须等待 index.js 加载和执行完毕才能去做其它事情。
<script src="index.js"></script>
async(异步) 模式
async 模式下,JS 不会阻塞浏览器做任何其它的事情。它的加载是异步的,当它加载结束,JS 脚本会立即执行。
<script async src="index.js"></script>
defer(延缓) 模式
defer 模式下,JS 的加载是异步的,执行是被推迟的。等整个文档解析完成、DOMContentLoaded 事件即将被触发时,被标记了 defer 的 JS 文件才会开始依次执行。
<script defer src="index.js"></script>
从应用的角度来说,一般当我们的脚本与 DOM 元素和其它脚本之间的依赖关系不强时,我们会选用 async;当脚本依赖于 DOM 元素和其它脚本的执行结果时,我们会选用 defer。
添加删除了DOM节点会发生什么?(回流)
把回流的过程说一下就可以了
js中改变transform的left和right对比于css修改transform
我的回答:css中使用transform会促发CPU加速,使浏览器不会进行回流和重绘。但是如果用js改变的话我不确定会不会,这样吧,我盲猜一下我感觉它会,因为我记得我看过说要避免频繁的使用style,不过不知道自己说的对不对。所以相对于用js调用的话后者的性能肯定就会更好一些。
面试官:呵呵呵,这个你下去在了解一下吧
什么是GPU加速
在使用CSS3中的transform、opacity、filter这些属性的时候,能跳过布局和绘制流程,直接进入非主线处理的部分,即交给合成线程。
- 合成线程中会调用线程池进行GPU加速,因为GPU是比较擅长处理位图数据的
- 且它没有占有主线程
进程和线程的区别
进程:资源分配的最小单位
线程:资源调度的最小单位
面试官;"你是不是回答反了?算了算了,我们不绕了,这个问题就这样吧"
(上面这个是正确的,当时应该是答反了)
做过H5页面没有?你怎样适配移动端的
做的少,然后我提到了在程序初始化的时候可以使用以下方式来修改根节点的字体大小:
(假设你需要的1rem = 20px)
(function () {
var html = document.documentElement;
function onWindowResize() {
html.style.fontSize = html.getBoundingClientRect().width / 20 + 'px';
}
window.addEventListener('resize', onWindowResize);
onWindowResize();
})();
document.documentElement:获取document的根元素html.getBoundingClientRect().width:获取html的宽度(窗口的宽度)- 监听
window的resize事件
一般还需要配合一个meta头:
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-sacle=1.0, maximum-scale=1.0, user-scalable=no" />
HTTP/2对比HTTP1.1
- 使用
HPACK算法进行头部压缩,HTTP/2当中废除了起始行的概念,将起始行中的请求方法、URI、状态码转换成了头字段,不过这些字段都有一个":"前缀,用来和其它请求头区分开。 - 使用二进制分帧解决了HTTP层面的队头阻塞,即多个请求都通过一个TCP连接并发地完成,实现多路复用。
- 服务器推送。服务器不再是完全被动地接收请求,响应请求,它也能新建 stream 来给客户端发送消息
- 新的二进制格式。HTTP/2采用二进制格式传输数据,相比于HTTP/1.1的文本格式,二进制格式具有更好的解析性和拓展性。
HTTP/2是怎么解决队头阻塞的
(当时只答出了第一段话)
HTTP/2引入了一个二进制分帧层,客户端和服务端进行传输时,数据会先经过二进制分帧层处理,转化为一个个带有请求ID的帧,这些帧在传输完成后根据ID组合成对应的数据。
所以原本一个个完整的HTTP请求报文变成了现在的一堆乱序的二进制帧,这些二进制帧因为不存在先后顺序所以也就不会排队等待,也就没有了HTTP队头阻塞的问题。
通信双方都可以给对方发送二进制帧,这种二进制帧的双向传输的序列,就叫做流。HTTP/2在一个TCP连接上来进行多个数据帧的通信,这就是多路复用的概念。
(所谓的乱序,指的是不同 ID 的 Stream 是乱序的,但同一个 Stream ID 的帧一定是按顺序传输的。)
HTTP/2是如何压缩头部的
(回答参考:https://juejin.im/post/5e76bd516fb9a07cce750746#heading-91 (opens new window))
主要是通过HPACK算法来实现压缩头部的功能,其主要有以下两个亮点:
- 首先是在服务器和客户端之间建立哈希表,将用到的字段存放在这张表中,那么在传输的时候对于之前出现过的值,只需要把索引(比如0,1,2,...)传给对方即可,对方拿到索引查表就行了。这种传索引 的方式,可以说让请求头字段得到极大程度的精简和复用。
- 其次是对于整数和字符串进行哈夫曼编码 ,哈夫曼编码的原理就是先将所有出现的字符建立一张索引表,然后让出现次数多的字符对应的索引尽可能短,传输的时候也是传输这样的索引序列 ,可以达到非常高的压缩率。
为什么说HTTPS比HTTP安全呢
- 通过混合加密保证传输的数据不被窃听
- 通过数字签名的方式保证数据不会被篡改
- 通过数字证书保证服务器身份的真实性
说一下对称加密和非对称加密
对称密钥加密是最简单的一种加密方式,它的加解密用的都是相同的密钥,这样带来的好处就是加解密效率很快,但是并不安全,如果有人拿到了这把密钥那谁都可以进行解密了。
而非对称密钥会有两把密钥,一把是私钥,只有自己才有;一把是公钥,可以发布给任何人。并且加密的内容只有相匹配的密钥才能解。这样带来的一个好处就是能保证传输的内容是安全的,因为例如如果是公钥加密的数据,就算是第三方截取了这个数据但是没有对应的私钥也破解不了。不过它也有缺点,一是公钥因为是公开的,谁都可以过去,如果内容是通过私钥加密的话,那拥有对应公钥的黑客就可以用这个公钥来进行解密得到里面的信息;二来公钥里并没有包含服务器的信息,也就是并不能确保服务器身份的合法性;并且非对称加密的时候要消耗一定的时间,减低了数据的传输效率。
HTTP请求的什么时候用的对称加密什么时候非对称加密
在建立连接的时候为了保证双方都能拿到对称密钥,所以需要使用非对称加密
而双方都拿到了这把对称密钥之后,就可以用这把对称密钥进行对称加密了。
对称加密的原理
(面试官提示万变不离其宗...可我还是悟不出来)
如果让你去实现一个CSRF攻击你会怎做?
当时答的只知道CSRF的攻击原理,但是不知道怎么去做...
还知道其它的攻击方式吗?
Vue中key的作用
key的作用是尽可能的复用 DOM 元素。
新旧 children 中的节点只有顺序是不同的时候,最佳的操作应该是通过移动元素的位置来达到更新的目的。
需要在新旧 children 的节点中保存映射关系,以便能够在旧 children 的节点中找到可复用的节点。key也就是children中节点的唯一标识。
如果我将key设置为了一个Math.random()可以吗
这道题我开始没太理解面试官的意思,然后他提示了我:回到key设计的初衷。之后开着玩笑的说了一句:"我在给你点时间思考一下,我挺希望你能答上来的。"
我:对不起我可能要让你失望了,我确实没想出来
面试官:嗯...没关系问题不大哈,这个问题我们过吧
(不过在最后面试完之后我也有问面试官这个问题,他说:key它就是为了保证我们的DOM节点能够复用,如果你都把它设置为了一个随机数的话,那每次重写渲染都会是另一个数了根本不可能达到复用的效果)
😂...绝了,原来想问的是这个意思,是我学艺不精了。
如果让你设计一个双向绑定你会如何设计
我:"我有了解Vue的双向绑定原理,如果你想听的话我可以说给你听"
面试官:"不用,你就大致说一下就可以了,让我知道你确实是了解了"
我:"巴拉巴拉"
如何实现if(a===1&&a===2&&a===3)
由于双向绑定的时候提到了Object.defineProperty()属性,面试官可能就想到了这道题。
这里其实我应该反思一下自己...
在面试官还没说完题目的时候我就急着先说自己知道甚至还想问面试官是不是这道题,这样显然是不好的,可能也是和面试官的面试氛围太好了...放飞了自我吧。但还好面试官不和我斤斤计较。
是有看过这道题吗?这么快的就回答上来了
😂😂😂,老实回答,在自己的文章中有写到这道题,所以很快就知道你想考的是什么了。
之后面试官说:"嗯呢,我昨天也有看了一下你的文章,lv4,望尘莫及..."
我:哈哈哈哈,没有没有,您自谦了,您只是没有写而已
(不能膨胀,谦虚)
你觉得我还有哪些问题没有问到的,也就是你可以说一下你的加分项
5月16日
二面
面试形式:电话面
面试时常:46分钟
面试感悟:面试官相对于一面的面试官来说会严肃一些,总体面试氛围也还可以。有很多问题,例如问到ngnix或者node,我表明了自己不熟之后也没有再问了。面到后面面试官的语气也和蔼了很多,我认为和一面一样都是比较好的面试体验吧。
说一下你们权限的控制,路由权限以及按钮权限
按钮权限除了用你现在的方式你还能想到更好的吗?比如封装一个组件
没有...
你们的token一般是放在哪里
token放在Cookie和放在localStorage、sessionStorage中有什么不同吗
Cookie存在哪些安全问题?如何预防?
SameSite设置为了lax之后是怎样来控制Cookie的发送的
如果顶级域名不同会发送吗
还有哪些前端安全性问题
如果使用jsonp的话会有什么安全问题吗?
你们有做过单点登陆吗
有用过ngnix吗?用它做过哪些事?
有用过node吗?比如用它写一些中间层
项目里做过哪些优化?
你认为你做的项目最大的亮点在哪里
项目中碰到的技术难点
是什么让你有动力写bpmn.js教材呢
有看过哪些源码呢
有给git上的比较好的项目提过pull吗
如果现在给你一个React的项目你觉得自己能多久上手呢
你的职业规划是怎样呢
说一下你的期望薪资吧?
有对比过深圳和广州这边的薪资吗?
5月18日
HR面
面试形式:微信视频
面试时长:50分钟
面试感悟:HR小姐姐很漂亮。然后问了我是否单身,那边也有很多单身的小姐姐。我说如果有缘的话要给我介绍一波。整个氛围还是比较轻松的。问了挺多问题的,我大概挑一些列举,其它的问题在别的面试官那里也有问到我就不重复了。另外在面试完之后,她告诉我,HR还会有二面,请等待通知...
有了解过我们公司吗?
之前不是在深圳吗?为什么打算来广州?
人生中有没有经历过什么对你触动比较大的事情?
有,失恋那次,但我总不能说这个吧。说点别的。
父母是如何看待你的工作的?
你现在单身吗?
单身!单身!我单身!(你要给我介绍女朋友吗?)
工作之余的兴趣爱好
期望薪资给不到怎么办
5月23日
HR二面
面试形式:微信视频
面试时长:58分钟
面试感悟:二面的HR小姐姐也很漂亮😂...开始的HR小姐姐并没有骗我,哈哈哈,开个玩笑,收。其实到了这一步,面试的公司基本就挺想要你了,所以问题也都是一些关于你自己对公司的看法,以及你未来的一个人生或者职业规划。关于这些问题,你如实回答就可以了。就比如HR问你:你是否打算在广州长期发展呀,会不会干了一年之后就又跳了呢?之类的。
