深圳某国内直播公司
1. 输入URL到页面呈现
(必问...)
2. 为什么说script标签建议放在body下面?
JS代码在加载完之后是立即执行的,且JS代码执行时会阻塞页面的渲染。
3. 为什么说script标签会阻塞页面的渲染呢?渲染线程和js引擎线程不是分开的吗?
JS属于单线程,当我们在加载script标签内容的时候,渲染线程会被暂停,因为script标签里可能会操作DOM的,所以如果你加载script标签又同时渲染页面肯定就冲突了,因此说渲染线程(GUI)和js引擎线程互斥。
4. 协商缓存说一下
Last-Modefied配合If-Modified-Since
ETag配合If-None-Match
(当时面试官还重复了一下我说的这4个头部字段,自己回顾了一下我说的对不对,好可爱~)
5. HTTP中的Keep-Alive有了解过吗?
- Keep-Alive是HTTP的一个头部字段Connection中的一个值,它是保证我们的HTTP请求能建立一个持久连接。也就是说建立一次TCP连接即可进行多次请求和响应的交互。它的特点就是只要有一方没有明确的提出断开连接,则保持TCP连接状态,减少了TCP连接和断开造成的额外开销。
- 另外,在HTTP/1.1中所有的连接默认都是持久连接的,但是HTTP/1.0并未标准化。
6. 跨域有了解吗?如何解决跨域?
- 我工作中碰到主要是利用CORS来解决跨域问题,说了一下它的原理以及后台需要如何做。
- 另外说到了JSONP的原理,以及它的优点:兼容性好;缺点:只能进行GET请求,且有安全问题。
- 还有说到了ngnix反向代理来解决跨域。
7. WebSocket有了解过吗?它也可以跨域的
这个当时答的没用过。
我知道它是能使得客户端和服务器之间存在持久的连接,而且双方都可以随时开始发送数据,这种方式本质没有使用 HTTP 的响应头,因此也没有跨域的限制。
8. 前端安全方面?XSS?CSRF?
(必问...)
XSS
XSS(Cross Site Script)跨站脚本攻击。指的是攻击者向网页注入恶意的客户端代码,通过恶意的脚本对客户端网页进行篡改,从而在用户浏览网页时,对用户浏览器进行控制或者获取用户隐私数据的一种攻击方式。
主要是分为三种:
- 存储型 :即攻击被存储在服务端,常见的是在评论区插入攻击脚本,如果脚本被储存到服务端,那么所有看见对应评论的用户都会受到攻击。
- 反射型 :攻击者将脚本混在URL里,服务端接收到URL将恶意代码当做参数取出并拼接在HTML里返回,浏览器解析此HTML后即执行恶意代码
- DOM型 :将攻击脚本写在URL中,诱导用户点击该URL,如果URL被解析,那么攻击脚本就会被运行。和前两者的差别主要在于DOM型攻击不经过服务端
如何防御XSS攻击
- 输入检查:对输入内容中的script和
<iframe>等标签进行转义或者过滤 - 设置httpOnly:很多XSS攻击目标都是窃取用户cookie伪造身份认证,设置此属性可防止JS获取cookie
- 开启CSP,即开启白名单,可阻止白名单以外的资源加载和运行
CSRF
CSRF攻击(Cross-site request forgery)跨站请求伪造。是一种劫持受信任用户向服务器发送非预期请求的攻击方式,通常情况下,它是攻击者借助受害者的 Cookie 骗取服务器的信任,但是它并不能拿到Cookie,也看不到Cookie的内容,它能做的就是给服务器发送请求,然后执行请求中所描述的命令,以此来改变服务器中的数据,也就是并不能窃取服务器中的数据。
防御主要有三种:
- 验证Token:浏览器请求服务器时,服务器返回一个token,每个请求都需要同时带上token和cookie才会被认为是合法请求
- 验证Referer:通过验证请求头的Referer来验证来源站点,但请求头很容易伪造
- 设置SameSite:设置cookie的SameSite,可以让cookie不随跨站请求发出,但浏览器兼容不一
点击挟持
- 诱使用户点击看似无害的按钮(实则点击了透明 iframe 中的按钮).
- 监听鼠标移动事件,让危险按钮始终在鼠标下方.
- 使用 HTML5 拖拽技术执行敏感操作(例如 deploy key).
预防策略:
- 服务端添加
X-Frame-Options响应头,这个 HTTP 响应头是为了防御用 iframe 嵌套的点击劫持攻击。 这样浏览器就会阻止嵌入网页的渲染。 - JS 判断顶层视口的域名是不是和本页面的域名一致,不一致则不允许操作,
top.location.hostname === self.location.hostname; - 敏感操作使用更复杂的步骤(验证码、输入项目名称以删除)。
9. setTimeout的执行原理(EventLoop)
(必问...)
setTimeout的运行机制:执行该语句时,是立即把当前定时器代码推入事件队列,当定时器在事件列表中满足设置的时间值时将传入的函数加入任务队列,之后的执行就交给任务队列负责。但是如果此时任务队列不为空,则需等待,所以执行定时器内代码的时间可能会大于设置的时间
说了一下它属于异步任务,然后说了一下还有哪些宏任务以及微任务,最后说了一下EventLoop的执行过程。
- 一开始整个脚本作为一个宏任务执行
- 执行过程中同步代码直接执行,宏任务进入宏任务队列,微任务进入微任务队列
- 当前宏任务执行完出队,检查微任务列表,有则依次执行,直到全部执行完
- 执行浏览器UI线程的渲染工作
- 检查是否有Web Worker任务,有则执行
- 执行完本轮的宏任务,回到2,依此循环,直到宏任务和微任务队列都为空
10. requestAnimationFrame有了解过吗?
(啪啪啪,不长记性,其实之前面试有被问过,但是忘了再去了解了,这就吃亏了,没答上来)
requestAnimationFrame是浏览器用于定时循环操作的一个接口,类似于setTimeout,主要用途是按帧对网页进行重绘。对于JS动画,用requestAnimationFrame 会比 setInterval 效果更好。
11. requestAnimationFrame和setTimeout的区别?
同上...
12. 平常工作中ES6+主要用到了哪些?
(下面看着很多,但我肯定不是全答哈,挑了几个来回答)
ES6:
- Class
- 模块import和export
- 箭头函数
- 函数默认参数
...扩展运输符允许展开数组- 解构
- 字符串模版
Promiselet constProxy、Map、Set- 对象属性同名能简写
ES7:
includes**求幂运算符
ES8:
async/awaitObject.values()和Object.entries()padStart()和padEnd()`Object.getOwnPropertyDescriptors()- 函数参数允许尾部
,
ES9:
for...await...of...展开符合允许展开对象收集剩余参数Promise.finally()- 正则中的四个新功能
ES10:
flat()flatMap()fromEntries()trimStart和trimEndmatchAllBigInttry/catch中报错允许没有err异常参数Symbol.prototype.descriptionFunction.toString()调用时呈现原本源码的样子
13. 如何在前端实现一个图片压缩
实话实话没做过,但是后来面试官告诉我:可以使用canvas来实现。具体做法等我写篇文章哈。
14. 你上家公司主要是做什么的?
15. 团队多少人呢?
1个前端(我),1个小程序老哥(IOS转行的),6个后台。
16. 项目中有碰到什么难的问题吗?如何解决的?
例举了我最经典的bpmn.js,以此来引出我写了很多关于这方面的教材,以及建立了微信群,为国内的bpmn.js社区贡献了一份力量...怎么高大上怎么来...
当然也有提到我GitHub上的bpmn-chinse-document项目只有100多的Star,他说理解,毕竟这东西用的人不是很多。
17. 期望薪资多少?
喊了个挺高的数,老哥笑了笑,你这个工作年限我们可能给不到,然后扯了点别的。
18. 还有什么想要问我的吗?
- 团队人员分布情况
- 技术栈
- 我进去主要是负责哪块内容
- 年终奖/季度奖
- 调薪的频率以及幅度
- 加班多不多
