yacan8 / blog

杨溜溜的个人博客,个人学习知识总结
https://github.com/yacan8/blog
826 stars 118 forks source link

记一次前端面试的全过程 #19

Open yacan8 opened 4 years ago

yacan8 commented 4 years ago

引言

接上一篇面试总结一年半经验,百度、有赞、阿里面试总结,把这段时间的面试结束一下吧。

本文主要记录一下当天面试的全过程(可能有遗漏,事隔三四天了,我已经尽量回忆了),答案亦为参考答案,仅供借鉴。

正文

有赞一面结束后过了两天就收到了二面的邀请,我回复面试邀请的短信,说最近可能请假太多,能不能约到晚上面试,对方很很爽快的答应了,就约在了晚上七点半,我回复可以的,然后第二天,收到了确切的面试的时间和地点,时间定在了晚上7点15分。

到了面试当天,我提前了五分钟下班,照着百度地图的提示路线(约1小时9分钟),到了公交站等车。。。然后等呀等,等了十五分钟公交还没来,怕自己迟到,就打了个滴滴过去,到了面试地点之后上到了公司的前台,前台没有人,可能是因为到饭点了,前台去吃饭了吧。然后看到前台那层楼好多人在打乒乓球,大家也玩得挺开心,看起来环境也很不错,当时想,诶呀,原来有赞的环境这么好。等了一会儿之后,看了一下短信,发现面试邀请里留有面试官的联系电话,果断打了过去,过了一会儿面试官到前台接我,然后找了一个会议室,开始了当天的面试。


面试官:先自我介绍吧

我:巴拉巴拉...

面试官:先说一下你上一家公司的研发部署流程

我:巴拉巴拉...(其实这个是我绝活,每次都可以吹很久)

面试官:既然你们是文件覆盖式发布,那你们的缓存是怎么刷新的

我:从公司的业务出发,巴拉巴拉...(还没说完)

面试官:那我现在就不谈业务,你说一下浏览器的缓存方案吧

我:哦,脱离业务呀,首先,浏览器有两种缓存方案,一种是强缓存一种是协商缓存。

面试官:嗯,那怎么使用强缓存?

我:浏览器在第一次请求资源的时候,服务端响应头里可以设置expires字段,该字段表示该资源的缓存过期时间,第二次请求的时候,如果时间还在该缓存时间之内,则会直接使用缓存,否则重新加载资源,这个expires字段有个缺陷,就是它必须服务端和客户端的时间严格同步才能生效,所以现在很多人不会使用改方案。另外一种方案是第一次请求资源的时候,服务端设置响应头cache-control: max-age,这样设置的意思是告诉浏览器,这个资源什么时候过期,等第二次请求资源的时候,判断是否超出了过期时间,如果没超出,直接使用缓存。

面试官:cache-control这个头是服务端设置的还是客户端设置的?

我:cache-control服务端设置的

面试官:cache-control的其他值,你也说一下吧

我:首先是public,客户端和服务端都可以缓存;然后是private,只能客户端缓存;no-store,不使用缓存;no-cache,使用协商缓存。

面试官:那你往下说,说一下协商缓存

我:协商缓存有两种,一种是Last-Modified,就是第一次请求资源的时候,服务端会在响应头里面设置该字段,表示该资源的最后修改时间,浏览器第二次请求该资源的时候,会在请求头里面加上一个字段If-Modified-Since,值为第一次请求的时候服务端返回的Last-Modified的值,服务端会判断资源当时的最后更改时间与请求头里面的If-Modified-Since字段是否相同,如果相同,则告诉客户端使用缓存,否则重新下载资源。然后另外一种协商缓存时使用ETag,原理与Last-Modified类似,就是第一次请求的时候,服务端会根据资源的内容或者最后修改时间生成一个标识,然后在响应头里面设置为ETag返回给客户端,客户端第二次请求的时候会在请求头里面带上这个ETag,也就是在请求头里面加上If-None-Match字段,服务端接收到了ETag之后判断是否与原来第一次的标识相同,如果相同,则告诉客户端使用缓存。

说一下Last-modified/If-Modified-Since和If-None-Match/ETag两种方案的优缺点

我:嗯呢,这个我想一想(我并不知道,假装思考一下)......我觉得其实ETag其实也是有的时候是根据资源的最后修改时间生成的,原理和Last-modified好像有点类似,而ETag需要耗费服务端的资源去生成,所以性能较低。。。(虽然不会,也尽量说说,万一面试官也不知道呢。哈哈哈哈)

面试官:那说一下性能优化的方案吧

我:首先,减少HTTP请求次数,比如说合并CSS和JS文件,但是也不要完全的合并在同一个文件里面,一个域名分散三四个资源,这样方便浏览器去并行下载,当然浏览器对每个域名的并行下载个数有限制,一个域名分配三四个资源虽然增加了HTTP请求数量,但是对比并行下载来说,性价比更高。

面试官:为什么浏览器要限制同一域名并行下载资源的个数。

我:嗯呢,这个我也想一下(其实我也不知道)......这个我没有深究过,难道是因为浏览器启动了太多下载线程的原因?

面试官:下载资源和线程有什么关系?

我:除了了每个标签页是一个进程以外,浏览器有一个进程是专门用来管理下载,我觉得大概是每下载一个资源启动一个线程吧(反正我也不知道,也猜猜结果是不是这样)

面试官:(沉默了一会儿),进程和线程区别是什么

我:进程是分配内存的最小单位,线程是CPU调度的最小单位,进程可以包含多个线程。

面试官:nodejs用得多吗?说一下nodejs线程之间是怎么通信的

我:nodejs用的比较少,nodejs可以启动子线程,然后用主线程来监听订阅子线程的消息,子线程之间的通信,由主线程来控制。

面试官:好吧,性能优化继续往下说

我:减少HTTP请求数量还可以把图标合并在同一张图片里面,使用的时候用background-position去控制。然后首屏的时候图片使用懒加载的形式,尽量在需要显示的时候在加载它,当然占位符和图片尽量指定宽度和高度,避免图片加载完之后替换图片浏览器会进行回流。

面试官:图片懒加载怎么实现

我:监听浏览器的滚动事件,结合clientHeight、offsetHeight、scrollTop、scrollHeight等等变量计算当前图片是否在可视区域,如果在,则替换src加载图片,当然这个滚动事件要主要节流。

面试官:怎么判断图片是否加载完成

我:使用onload事件。

面试官:好吧,你继续往下说。

我:性能优化的话,还可以合理的利用缓存,尽量把CSS和JS文件使用外链的形式,虽然使用内联的CSS和JS在空缓存的时候更快,因为内联的样式和脚本不需要发送HTTP请求,但是为了尽量发挥浏览器的缓存功能,尽量使用外链形式。

我:然后尽量把CSS放在头部,JS放在底部。

面试官:假如现在页面里放在head的css文件下载速度很慢,页面会出现什么情况?

我:大概页面会等待这个CSS的下载,这个时候页面是白屏状态,然后这个CSS资源会有一个超时时间,假如超过了这个超时时间,这个资源相当于会下载失败,浏览器会直接跳过这个CSS资源,根据已有的CSS资源生成CSS规则树,进而生成Render树,然后渲染页面。

面试官:假如我现在在页面动态添加了一个CSS文件,页面一定会回流吗?

我:只要加入的CSS影响到了页面的结构,那么浏览器就会回流。

面试官:例如页面这个CSS文件中有translate3d呢?

我:其实我感觉它不会回流,因为translate3d只是变换了自己的位置,不会影响其他元素的位置,但是实际上是会造成回流的。

面试官:那假如我在页面里面加了一个\

\
呢,会回流吗

我:不会,因为没有影响页面结构的变化。

面试官:好吧,那你继续往下说

我:性能优化,尽量使用CDN。

面试官:CDN的原理是啥?

我:首先,浏览器会先请求CDN域名,CDN域名服务器会给浏览器返回指定域名的CNAME,浏览器在对这些CNAME进行解析,得到CDN缓存服务器的IP地址,浏览器在去请求缓存服务器,CDN缓存服务器根据内部专用的DNS解析得到实际IP,然后缓存服务器会向实际IP地址请求资源,缓存服务器得到资源后进行本地保存和返回给浏览器客户端。

面试官:你来实现以下刚刚说的节流函数吧

。。。当时有点不记得什么是防抖,什么节流,把函数写成了防抖。(这个时候有一个人走进了会议室,好像是一面小哥)

var debounce = function(fn, delay, context) {
  let timer = null;
  return function() {
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      const arg = Array.prototype.slice.call(arguments);
      fn.apply(context, arg);
    }, delay)
  }
}

// 测试部分
var run = function(text) {
  console.log(text);
}

run = debounce(run, 200);

run('run1');
run('run2');

setTimeout(() => {
  run('run3');
}, 201)

面试官:我这边没有什么问题了,你还有什么要补充的吗?

我:那我把性能优化这个问题说完?

面试官:可以。

然后我开始描述使用webpack使用进行减少js文件的体积,可以使用babel-plugin-import、babel-plugin-component、webpack.ContextReplacementPlugin、webpack.IgnorePlugin...

面试官:这个我知道。你还有什么问题吗?(大概是想结束面试了吧,不想让我往下说了)

我:巴拉巴拉。。。问了很多关于有赞公司的问题,比如公司有多少层楼啊、公司主要技术栈啊、公司主要做2B还是2C的啊,公司有多少前端的啊(本人可能还是太啰嗦)

最后问了一个问题,问了一下面试官本次便是的评价是啥,面试官只回了一句,还好吧。然后面试到此结束了,全称大概一个多小时。


面试结束后,面试官送我到电梯口。。。可以说楼层是真的高,上楼和下楼都需要等很久的电梯。。。到了外面之后,下着大雨,落汤鸡似的又打了个滴滴回家,结束了当天的面试之旅。

最后

直到昨天,收到了有赞的面试结果回复邮件,告知没有合适的职位(有赞还是挺不错的,没通过面试还通知一下),心里虽然有点不甘,但是想想确实可能是自己不够优秀,或者是自己面得不是很好,或者是自己的能力跟公司的职位不太匹配。

在上一篇面试总结中一年半经验,百度、有赞、阿里面试总结,部分同学关心最后面试结果情况,情况是已经有幸的收到了百度的offer,蚂蚁金服的一面面试已经过一周了,不知道是因为流程太长还是一面被挂了。

这个时候一想,其实面试还是有很大的运气成分在里面,正好公司需要,正好你又合适,这个时候就很幸运。

turkyden commented 3 years ago

很棒,博主现在工作第几年了?很强啊,会吹,都把面试官吹烦了。

yacan8 commented 3 years ago

很棒,博主现在工作第几年了?很强啊,会吹,都把面试官吹烦了。

当时面试的时候才工作一年半,现在回头看自己的回答,其实很多都回答得不好。

turkyden commented 3 years ago

赞!