抱最乐观的心态去期待,为最坏的结果作准备。
字节跳动一二面:
IO是什么?
vue的路由模式有哪几种?分别是怎么实现的?
什么是闭包?
闭包就是一个函数在执行的时候,即使不是在函数声明定义的执行上下文,仍然可以访问声明定义时的执行上下文。
比较经典的场景就是一个函数返回一个内部函数,该内部函数引用了外部函数的变量,当在函数之外下执行返回的
函数时,仍然可以正确访问引用的变量。
以下代码会输出什么?
var x = 1;
function fn() {
var x = 2;
this.fn1 = function () {
console.log(x);
}
this.fn2 = function () {
console.log(this.x);
}
this.fn3 = function () {
return this.fn1;
}
this.fn4 = function () {
return this.fn2;
}
console.log(this.x);
}
fn(); //输出1,函数内的this使用默认绑定,指向全局对象window,执行的过程把fn1、fn2、fn3、fn4挂载在window上。
fn1(); //输出2,执行的是window上的fn1;fn1和fn形成了闭包,x访问fn的x。
fn2(); //输出1,执行window上的fn2,this指向window。
var obj = new fn(); //输出undefined,具体参考new的实现过程,为实例obj绑定了fn1、fn2、fn3、fn4。
obj.fn1(); //输出2,执行的是obj上的fn1,new的过程中fn的执行构成了闭包。
obj.fn2(); //输出undefined,实例obj上没有x属性
obj.fn3()(); //输出2,理由同obj.fn1();
obj.fn4()(); //输出1,理由同obj.fn2();
什么XSS攻击?
Cross-Site Scripting(跨站脚本攻击)简称 XSS,是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚
本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,
进而危害数据安全。
XSS攻击的原理是什么?
攻击者注入的恶意代码未经过滤,和网站的正常代码混在一起,浏览器无法分辨那些脚本是可信的,导致恶意脚本
被执行。而由于直接在用户的终端执行,恶意代码能够直接获取用户的信息,或者利用这些信息冒充用户向网站发
起攻击者定义的请求。在部分情况下,由于输入的限制,注入的恶意脚本比较短,但可以通过引入外部的脚本,并
由浏览器执行,来完成比较复杂的攻击策略。
XSS攻击的分类有哪些?
1.存储型,属于服务端的漏洞,常见的有论坛发帖和用户评论等。
2.反射型,属于服务端的漏洞,常见的有URL注入,比如网站搜索功能、。
3.DOM型,属于前端的漏洞,常见的有把用户的输入直接作为HTML输出。
1.存储型和反射型的区别?
存储型的恶意注入脚本会存储在数据库中,而放射型不会。
2.DOM型作为前端和服务端的两种类型有什么区别?
存储型和反射型两种类型的恶意注入脚本由服务器取出,然后由浏览器执行。
DOM型的恶意注入脚本的取出和执行都是由浏览器完成。
存储型的XSS攻击的过程?
1.攻击者将恶意代码提交到目标网站的数据库中。
2.用户打开目标网站时,网站服务端将恶意代码从数据库取出,拼接在 HTML 中返回给浏览器。
3.用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
4.恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
反射型的XSS攻击的过程?
1.攻击者构造出特殊的 URL,其中包含恶意代码。
2.用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。
3.用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
4.恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
DOM型的XSS攻击的过程?
1.攻击者构造出特殊的 URL,其中包含恶意代码。用户打开带有恶意代码的 URL。
2.用户浏览器接收到响应后解析执行,前端 JavaScript 取出 URL 中的恶意代码并执行。
3.恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
XSS预防的手段有哪些?
1.存储型和反射型的攻击点主要发生在后端动态拼接HTML时,在项目允许的情况下,使用纯前端渲染,后端的数据
全部作为文本输出而不是动态HTML渲染。在某些网站不可避免地使用服务端渲染时,一方面可以手动转义动态输出
地HTML、URL拼接或者JSON数据。另一方面可以使用具有自动分析转义功能地安全模板引擎比如EJS。
2.前端渲染数据地时候,应该避免或者禁止直接被用户地输入渲染HTML。
3.利用浏览器地CSP(安全内容策略)禁止执行外域或者是未授权地脚本。
4.对于不信任地输入,可以限制输入地长度加大攻击地难度。
5.谷歌地Automatic Context-Aware Escaping,自动上下文感知转义。
如何回答XSS攻击的面试题?
1.xss攻击的全称,大概攻击过程,对网站安全的影响。2.xss攻击的分类,存储型,反射型,DOM型。3.不同种类攻击的大概过程和区别。4.结合xss攻击的过程,针对攻击过程中的不同阶段采用针对性的预防手段。
如何回答怎样预防xss攻击的面试题?
1.xss的大概过程是攻击者通过各种各样的手段在目标网站中注入攻击代码,用户下一次访问页面时,浏览器
执行预先准备好的攻击代码,从而窃取用户的数据,或者是窃取本地cookie发往攻击的网站。
2.从输入的源头过滤转义攻击者注入的攻击代码,过滤转义的时机可以在请求之前前端过滤,也可以在后端解
析请求的时候过滤转义。攻击手段多种多样,前端无法覆盖所有的情况,请求的数据可能要多端显示,不同端
的编码会有显示异常。
3.由于在注入代码输入的源头过滤有很大的局限性,有必要在渲染页面的时候阻止注入代码的执行,可以采用
纯前端渲染的形式,后端只提供数据由前端渲染,渲染的时候渲染成文本的形式,避免直接渲染HTML。考虑网
站SEO和渲染速度必须使用服务端渲染时,针对可能产生XSS攻击的地方做转义处理或者使用内置了自动转义规
则的模板引擎。
4.在前端可以使用JavaScript直接生成添加HTML片段,使用的时候避免使用innerHtml、document.write、
vue的v-html,避免把不明代码作为内联事件处理函数、a标签的href属性值和可以执行代码字符串的API。
5.面对无法防止注入的攻击代码时,可以设置cookie的HTTPOnly和配置客户端的内容安全策略,拦截攻击代
码的请求,防止用户数据的丢失。
6.在开发阶段,借助XSS攻击字符串做一个手动的检测,或者是借助扫描工具比如Arachni发现潜在的攻击漏洞。
7.Google提出了Automatic Content-Awarde Escaping,可以在模板解析的时候,分析插入点所处的上下文
,选取合适的转义规则,支持该功能的模板有Go html/template和google clureso/template.
如何预防CSRF攻击?
1.同源检测
因为csrf的攻击大多数都是在第三方网站发起,都是跨域请求,服务器可以配置白名单或者是黑名单,拦截第
三方请求或者是不信任来源的请求。
通过origin请求头或者是referer请求头判断,
IE11在跨域请求不会携带origin,302重定向的情况下也不会携带origin字段。
referer由浏览器自动添加,浏览器的安全决定了referer的安全级别
2.CSRF-token验证,分布式验证。
3.双重cookie认证。cookie容易被xss攻击泄漏。
谈谈你对前端的理解?
1.前端在一个应用中的定位是一个用户和应用之间的桥梁的关系,前端作为一个应用的出口,也是用户进入应用系统
的入口,给用户的第一印象和操作体验很大程度上影响了用户下一次还会不会使用,所以前端和后端一样在应用的开
发中扮演着重要角色。
2.前端领域经历了刀耕火种的阶段,迎来了百花齐放的阶段,前端技术日新月异,出现了很多优秀的框架和工具,
给前端开发者提出了更高的要求,快速学习能力显得更加重要了。另一方面,大前端的流行很容易让前端开发者分散
注意力,迷失方向,建立牢固的基础以不变应万变。
进程和线程的区别?
1.进程时系统分配资源的基本单位,线程是系统任务调度和执行的基本单位。
2.每个进程有独立的代码和数据空间,进程之间切换开销比较大,线程可以看作轻量的进程,同类线程共享数据空
间,线程之间切换开销小。
3.系统中可以同时运行多个进程,一个进程可以有多个线程,一个CPU时间片只能执行一个线程。
常见的性能优化有哪些?
1.原生开发的时候,把引入JavaScript的script标签放在body底部,或者为script标签添加defer和async属性
异步加载js文件,避免阻塞页面渲染。
2.当首页比较复杂时,提取关键的CSS样式以内联的方式添加到首页HTML文件中,其他次要样式通过import异步的
方式引入。
3.原生操作手动操作的DOM的时候,避免操作引起页面频繁的回流和重绘。
4.对于一些博客类的网站,可以预测用户的操作路线,利用HTML5的资源提示符提前加载、解析接下来会用到的资源
,或者提前建立和服务器的连接。(DNS-prefetch、preconnect、preload、prerender).
5.使用vue开发项目的时候,可以使用针对vue做一些优化,对于比较大的第三库,可以利用import函数异步加载,
避免不使用的情况下加载增加打包的体积。
6.对于单页面应用,可以根据路由拆分模块,访问对应路由的时候采取异步加载对应的模块。
7.合理使用v-if、v-show和<keep-alive></keep-alive>组件,避免多余的重渲染。
8.使用webpack打包项目的时候,针对css中的背景图片,可以通过postcss-sprites生成雪碧图,减少HTTP请求。
9.合理配置的URL-loader的图片处理范围,把图片以base64编码的形式内联到HTML中,减少HTTP请求。
10.利用tree-shaking切割掉冗余的代码,减少打包的体积。
11.对于第三方不会经常变化的模块,可以利用代码分割提取出来异步加载,设置合理的hash配合浏览器缓存,减少
HTTP请求。
性能优化的原则?
1.依赖应用程序运行的数据而不是凭空想象。
2.不过早开启优化。
3.设定固定的指标和测试用例,避免过度优化。
4.深入理解业务,从需求出发,追求无损优化。
🚴♀️HTML、CSS和JavaScript是如何变成页面的?
渲染流水线
由于渲染机制过于复杂,渲染模块在执行过程会被划分为很多个子阶段,HTML经过这些子阶段最后输出像素,这个处理流程叫作渲染流水线。
构建DOM树、样式计算、布局阶段、分层、绘制、分块、光栅化、合成。
构建DOM树
HTML文件是纯文本,浏览器无法直接理解和使用,所以需要将HTML装换为浏览器能够理解的树形数据结构--DOM树,并提供操作这个数据结构的API。
解析CSS生成样式表
CSS样式文件是纯文本文件,浏览器无法直接理解和使用,所以需要将外部CSS文件,Style标签定义和内联样式装换为浏览器能够理解的数据结构--样式表styleSheets,并提供操作这个数据结构的API。
样式的属性值标准化
解析生成的样式表,存在浏览器无法直接识别的属性值,比如em和rem会被转换为px,green会被转换为rgb(),bold装换为700.
样式计算
根据CSS样式的继承规则和层叠规则计算每个DOM元素的样式,并存储在DOM对象的ComputedStyle属性中。
构建渲染树
遍历DOM树生成一份DOM树的副本-渲染树,副本不包括DOM树中的隐藏元素和页面显示无光的标签元素比如<head>标签等。
去除隐藏元素的原因: 隐藏元素不占据空间,不影响后面的布局计算.
布局计算-回流
结合窗口的高度和宽度等信息,遍历渲染树,计算每个DOM元素在窗口中的几何坐标位置,并记录在当前的DOM元素中.
分层
为了方便实现3D动画 , 页面滚动 , z-indexing等效果,渲染引擎会为特定的节点生成专用的图层, 并生成一颗对应的图层树.
什么样的DOM元素会被提升为单独的一个图层?
使用position定位属性 z-index css滤镜 透明属性的元素都会被提升为单独的一层
需要裁剪或者滚动的地方会被提升为单独的一层
不被单独提升的元素, 会从属于父元素所在的图层
图层绘制
遍历图层树中的每一个图层, 渲染引擎回对图层树中的每个图层进行绘制, 绘制之前会生成绘制需要的绘制指令列表. 然后交给渲染进程的合成线程.
合成线程 - 分块
某些情况下, 一个图层的大小是视口大小的几倍, 用户看到的只是图层的一部分, 如果绘制出所有的图层, 会产生不必要的开销.
所以, 合成线程会将图层划分为图块, 优先处理视口附件的图块.
栅格化进程
将合成线程的要求, 把视口附近的图块生成位图. 栅格化过程都会使用GPU加速, 生成的位图保存在GPU内存中.
合成和显示
经过栅格化处理后, 每个图层都对应一张位图, 合成线程把所有的位图合成一张图片, 发送到显卡的后缓冲区中, 显示器会以特定的频率从显卡缓冲区中获取图片,显示在屏幕上.
🚴♀️重排, 重绘和合成
重排需要更新完整的渲染流水线, 所以开销也是最大的.
重绘跳过布局阶段, 直接进入绘制阶段, 执行效率会比重排操作高很多.
合成跳过主线程的布局和绘制阶段, 直接进入合成线程的合成操作, 效率是三者最高的.