JS部分
HTML + CSS
React
Vue
ES6
webpack,node.js,Git等
1.HTML5 存储类型有什么区别?
HTML5 能够本地存储数据,在之前都是使用 cookies 。HTML5 提供了两种本地存储方案: localStorage 用于持久化的本地存储,数据永远不会过期,关闭浏览器也不会丢失。 sessionStorage 同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。
2.cookie、localStorage、sessionStorage的区别?
特性 | cookie | localStorage | sessionStorage | indexDB |
---|---|---|---|---|
数据生命周期 | 一般由服务器生成,可以设置过期时间 | 除非被清理,否则一直存在 | 页面关闭就清理 | 除非被清理,否则一直存在 |
数据存储大小 | 4K~5k | 5M | 5M | 无限 |
与服务端通信 | 每次都会携带在 header 中,对于请求性能影响 | 不参与 | 不参与 | 不参与 |
从上表可以看到,
cookie
已经不建议用于存储。如果没有大量数据存储需求的话,可以使用localStorage
和sessionStorage
。对于不怎么改变的数据尽量使用localStorage
存储,否则可以用sessionStorage
存储。
3.节流和防抖
防抖:就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。假设我们网站有个搜索框,用户输入文本我们会自动联想匹配出一些结果供用户选择。
// 防抖
function debounce(fn, wait) {
var timeout = null;
return function() {
// 每次触发都判断一次定时器是否为空
// 只有第一次为空
if(timeout !== null){
// 如果非空就先清除,重新计时
clearTimeout(timeout);
timeout = setTimeout(fn, wait);
}
}
}
// 处理函数
function handle() {
console.log(Math.random());
}
// 事件
window.addEventListener('click', debounce(handle, 1000));
节流:就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率,
例如,滚动浏览器滚动条的时候,更新页面上的某些布局内容或者去调用后台的某接口查询内容。
// 节流(定时器):
var throttle = function(func, delay) {
var timer = null;
return function() {
var context = this;
var args = arguments;
// 每次触发都判断一次定时器是否为空
// 只有执行完才为空
if (!timer) {
// 如果为空才会触发,触发完时间恢复空值
timer = setTimeout(function() {
func.apply(context, args);
timer = null;
}, delay);
}
}
}
//处理函数
function handle() {
console.log(Math.random());
}
//事件
window.addEventListener('click', throttle(handle, 1000));
4.html5的语义化标签给我们带来了啥好处
- 结构清晰
- 可读性好
- 便于团队维护开发
- 搜索引擎可根据标签的语言确定上下文和权重问题,
- 容易被搜索引擎抓住机会
5.div+css 的布局较 table 布局有什么优点?(也可看作div+css布局较其他布局的优点)
- 改版的时候更方便 只要改 css 文件。
- 页面加载速度更快、结构化清晰、页面显示简洁。
- 表现与结构相分离。
- 易于优化(seo)搜索引擎更友好,排名更容易靠前。
- div+css布局的好处:
1.符合W3C标准,代码结构清晰明了,结构、样式和行为分离,带来足够好的可维护性。
2.布局精准,网站版面布局修改简单。
3.加快了页面的加载速度(最重要的)。
4.节约站点所占的空间和站点的流量。
5.用只包含结构化内容的HTML代替嵌套的标签,提高另外搜索引擎对网页的搜索效率。 - table布局的好处(table布局也不是一点用的没有,这点是毋庸置疑的)
1.容易上手。
2.可以形成复杂的变化,简单快速。
3.表现上更加“严谨”,在不同浏览器中都能得到很好的兼容。
6.hash、chunkhash、contenthash三者区别 链接
7.浏览器端 Event loop
执行栈在执行完同步任务后,查看执行栈是否为空,如果执行栈为空,就会去检查微任务(microTask)队列是否为空,如果为空的话,就执行Task(宏任务),否则就一次性执行完所有微任务。
每次单个宏任务执行完毕后,检查微任务(microTask)队列是否为空,如果不为空的话,会按照先入先出的规则全部执行完微任务(microTask)后,设置微任务(microTask)队列为null,然后再执行宏任务,如此循环。
微任务于宏任务面试题
8. 跨域的解决方案
9. 什么是BFC,介绍一下BFC的触发方式以及特性
BFC(Block formatting Context) ,即块级格式化上下文
- BFC的触发条件
- 根元素 html标签就是一个BFC
- float的值不为none
- overflow的值不为visible
- display的值为 inline-block/ table-cell/ table-caption/ flex/ inline-flex
- position的值为absolute或fixed
- BFC特性
- Box垂直方向的距离由margin决定,属于同一个BFC的两个相邻box的margin会发生重叠(应用:可以解释为什么margin上下会重叠,以及解决方法的原因)
- 计算BFC的高度时,浮动元素也参与计算(应用:可以解释为什么高度塌陷可以用overflow:hidden等方法解决)
- BFC的区域不会与float box发生重叠(应用:自适应两栏布局或者三栏布局<圣杯布局和双飞翼布局>)
- BFC内部的Box会在垂直方向,一个接一个的放置。
- 每个元素的margin box的左边会与包含块border box的左边相接触(对于从左到右的格式化,否则相反),即使存在浮动也会如此。
- BFC就是页面上的一个独立容器,容器里面的元素不会影响到外面的元素
10.介绍一下单页面和多页面的区别
单页面应用(SPA),通俗一点说就是指只有一个主页面的应用,浏览器一开始要加载所有必须的 html, js, css。所有的页面内容都包含在这个所谓的主页面中。但在写的时候,还是会分开写(页面片段),然后在交互的时候由路由程序动态载入,单页面的页面跳转,仅刷新局部资源。
多页面(MPA),就是指一个应用中有多个页面,页面跳转时是整页刷新
- 单页面的优点:
- 用户体验好,快,内容的改变不需要重新加载整个页面,基于这一点spa对服务器压力较小
- 前后端分离
- 页面效果会比较炫酷(比如切换页面内容时的专场动画)
- 单页面缺点:
- 导航不可用,如果一定要导航需要自行实现前进、后退。(由于是单页面不能用浏览器的前进后退功能,所以需要自己建立堆栈管理)
- 初次加载时耗时多
- 页面复杂度提高很多
11. 浏览器是怎样解析CSS选择器的
CSS选择器的解析是从右向左
解析的。若从左向右的匹配,发现不符合规则,需要进行回溯,会损失很多性能。若从右向左匹配,先找到所有的最右节点,对于每一个节点,向上寻找其父节点直到找到根元素或满足条件的匹配规则,则结束这个分支的遍历。两种匹配规则的性能差别很大,是因为从右向左的匹配在第一步就筛选掉了大量的不符合条件的最右节点(叶子节点),而从左向右的匹配规则的性能都浪费在了失败的查找上面。
而在 CSS 解析完毕后,需要将解析的结果与 DOM Tree 的内容一起进行分析建立一棵 Render Tree,最终用来进行绘图。在建立 Render Tree 时,浏览器就要为每个 DOM Tree 中的元素根据 CSS 的解析结果(Style Rules)来确定生成怎样的 Render Tree。
11.HTML5 应用程序缓存和浏览器缓存有什么区别
H5引入了应用程序缓存,意味着WEB应用可进行缓存,可在没有因特网时进行访问
应用程序缓存的优势:
1. 离线缓存:用户可在离线时使用它们
2. 速度:加载速度更快
3. 减少服务器负载:浏览器只从服务器下载更新的或者更改过的资源
12.xss、csrf的攻击和预防
xss 全称跨站脚本攻击
XSS攻击的原理就是 攻击者往 Web 页面里插入恶意的脚本代码(css 代码、Javascript 代码等) , 当用户浏览该页面时,嵌入其中的脚本代码会被执行,从而达到恶意攻击用户的目的,如盗取用户 cookie、破坏页面结构、重定向到其他网站等
预防
1、将httpOnly属性设置为true,这样使用js 就获取不到cookie了
2、只允许用户输入我们期望的数据,我们可以对输入数据进行验证
3、对发送的数据进行编码转义处理,或者使用正则替换
4、服务端也要做判断处理查看是否有XSS攻击,然后做转义处理;
csrf 跨站请求伪造
顾名思义就是伪造请求,冒充用户在站内的正常操作。攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来讲,这个请求是完全合法的,但是却完成了攻击者所期望的一个操作。而且你自己还不知道究竟是哪些操作。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…造成的问题包括:个人隐私泄露以及财产安全。
CSRF攻击原理如下:
- 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
- 此时用户登录网站A成功,可以正常发送请求到网站A
- 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
- 网站B返回一些攻击性代码,并发出一个请求要求访问网站A;
- 浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。
预防 :
1 尽量使用POST接口,限制GET接口
GET接口太容易被拿来做CSRF攻击,只要构造一个链接,便可以进行CSRF攻击。接口最好限制为POST使用,降低攻击风险。
当然POST并不是万无一失,攻击者只要构造一个form就可以,但需要在第三方页面做,这样就增加暴露的可能性
2 加入验证码
我们知道攻击者构造的就是一个伪请求,所以我们在提交的时候让用户去输入一下验证码或者是一些滑动验证码,这样能够确保这个行为是一个用户行为而非黑客行为,一般而言,简单的验证码也可能被破解的,但是一些智能地验证码还是很难被破解的
3 验证referer
我们知道在http协议的头部有一个字段叫referer,它能够记录当前一次请求的来源地址.如果黑客要对当前网站实施csrf的攻击,他只能在自己的网站构造请求,所以referer传过来的是和当前网站不同的域名,我们可以在后端判断一下,如果referer值不是当前的网站,那么直接就拒绝这个请求
4 使用token
在用户登录成功后,返回一个随机token给浏览器,当每次用户发送请求的时候,将token 主动发送给服务器端(为了安全,不建议将token以参数的形式传给服务器,可以将token存储在请求头中),服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。
13.客户端渲染和服务端渲染的区别
客户端渲染和服务端渲染
服务器端通过页面模板和数据生成HTML页面,返回给 客户端完整的html,这样浏览器就可以直接显示了
客户端渲染:后端提供一些api使得前端可以获取json数据,然后前端拿到json数据之后再在前端进行html页面拼接,然后展示在浏览器上
两者本质区别
客户端渲染和服务器端渲染的最重要的区别就是究竟是谁来完成html文件的完整拼接
优缺点分析
客户端:
优点:客户端渲染的优点就是网络传输的数据量比较小,减少了服务端的压力,前后端分离,前后端人员可以分工合作,代码耦合度低,并且前端人员可以有更多的选择性,比如使用单页面,可以有更好的用户体验,
缺点:就是不利于seo的优化,首次加载可能会比较慢,因为要加载很多js,css文件
服务端:
优点:不占用前端的资源 ,页面渲染快,并且有利于seo的优化
缺点:前后端不分离,开发时的耦合度很高,分工不明确,降低开发效率,用户量大的时候,对服务器的负荷也会增大
14.http的缓存机制
关于HTTP的缓存机制来说,这些缓存策略都会体现在HTTP的头部信息的字段上,这些策略会根据是否需要重新向服务器发起请求可以分为强缓存和协商缓存两大类。
强缓存: 请求某个资源文件时,服务端就会在response
header中对该资源文件做缓存配置:cache-control,常见的设置是max-age public private
no-cache no-store immutable等。当用户打开某页面,浏览器会判断缓存是否过期,没有过期就会从缓存中读取数据。
协商缓存: 协商缓存就是需要客户端和服务器两端进行交互的;每次请求回来的response
header中的etag和last-modified;下次请求带上,服务端会进行标识和对比,如果资源更新了就会返回新的资源和对应的etag和last-modified;反之资源没有变。
15.DOM 事件有哪些阶段?谈谈对事件代理的理解?
- DOM事件分为三大阶段:
- 捕获阶段(事件从Document节点自上而下向目标节点传播的阶段)
- 目标阶段(真正的目标节点正在处理事件的阶段)
- 冒泡阶段(事件从目标节点自下而上向Document节点传播的阶段)
-
事件代理 简单来说就是:事件不直接绑定到某个元素上,而是绑定到该元素的父元素上,进行触发事件操作时,在通过条件进行判断,执行事件触发后的语句。
事件代理的好处:(1)使代码更简洁;(2)节省内存开销;
16.你能描述一下渐进增强和优雅降级之间的不同吗?
- 渐进增强:针对低版本浏览器进行构建页面,保证最基本的功能实现,然后再针对高版本浏览器进行效果、交互等改进和追加功能,达到更好的用户体验。
- 优雅降级:是从一开始就构建一套完整的功能,然后在针对低版本浏览器进行兼容处理。
区别:
优雅降级是从复杂的现状开始,并试图减少用户体验的供给,意味着往回看;
而渐进增强则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要,意味着朝前看,同时保证其根基处于安全地带。
其实使用这两种设计范例的人都有其各自的观点:
- 渐进增强的观点认为应该关注内容的本身,不管建立网站的原因是什么,他们所有的相同点都是基于内容的,所以渐进增强成为一种更为合理的设计范例,这也是他被yahoo采纳并且构建的原因。
- 而优雅降级的观点认为应该针对那些最高级、最完善的浏览器来设计网站,那些被认为过时了的或者是有功能缺失的浏览器的测试工作应该安排在开发周期的最后阶段,并且把测试对象限定为主流浏览器的前一个版本。所以在这种设计范例下,旧版的浏览器就被认为仅能提供 “简陋却无妨” 的浏览体验。
18.静态资源放置于独立域名之下的好处
• 浏览器为提升页面显示效率,支持并发获取资源。浏览器对并发请求的数目有限制,这个限制是针对域名的,即针对同一域名(包括二级域名)在同一时间的并发请求数量有限制。如果请求数目超出限制,则会阻塞。因此,网站中对一些静态资源,使用不同的一级域名,可以提升浏览器并行请求的数目,加速界面资源的获取速度。
• 当静态资源与主服务在同一域名下的话,因为业务需要,主服务请求时需要传递cookie信息,每次静态资源的请求,都会发送同域名下的cookie。但其实对于静态资源,服务器无需对cookie进行任何处理,它们只是在毫无意义的消耗带宽。很多情况下cookie的path是在整个一级域名下可用的,如果你把静态资源设置成二级域名,那么它也避免不了cookie。
所以静态资源使用单独的域名,可以减少请求大小,提高网页性能。启用新的一级域名,每次请求浏览器不会携带cookie。这对于cookie内容比较大,并且流量大的网站会省去不少宽带费用
• 动静分离。静态资源与动态内容分离,有利于部署于CDN。静态资源独立部署,方便复用,放在一个服务器上的文件可以共其他服务器上的产品使用。 比如taobao.com和tmll.com都会用到tbcdn.cn上的静态资源,这些资源不必从属于某个产品。这样同时也有利于最大化利用客户端缓存。比如访问taobao.com,缓存了tbcdn.cn上的某个js文件,之后再访问tmll.com时,也用到此js文件,不必再从tbcdn.cn上下载,直接用客户端缓存即可。
19.为什么form表单提交没有跨域问题,但ajax提交有跨域问题?
其实说到跨域问题,原则上就是对数据安全的考虑。跨域问题 是 浏览器同源策略的一部分,form表单也好,ajax请求也好,都是需要后续的JS逻辑支撑才能完成需求,form在提交之后,是不会有数据返回的,原本提交页面的JS无法获取到新页面中的内容,这在浏览器看来是安全的;而ajax请求是要求有数据返回的,这就相当于未经别人允许去读取别人的东西,其实请求是已经发送出去了的,只是浏览器不允许你拿到响应的数据而已。
20.页面编码和被请求的资源编码如果不一致如何处理?
对于 ajax 请求传递的参数,如果是 get 请求方式,参数如果传递中文,在有些浏览器
会乱码,不同的浏览器对参数编码的处理方式不同,所以对于 get 请求的参数需要使用
encodeURIComponent
函数对参数进行编码处理,后台开发语言都有相应的解码 api。
对于 post 请求不需要进行编码
21.从浏览器地址栏输入url到显示页面的步骤
(1)从浏览器接收url到开启网络请求线程(这一部分可以展开浏览器的机制以及进程与线程之间的关系)
(2)开启网络线程到发出一个完整的HTTP请求(这一部分涉及到dns查询,TCP/IP请求,五层因特网协议栈等知识)
(3)从服务器接收到请求到对应后台接收到请求(这一部分可能涉及到负载均衡,安全拦截以及后台内部的处理等等)
(4)后台和前台的HTTP交互(这一部分包括HTTP头部、响应码、报文结构、cookie等知识,可以提下静态资源的cookie优化,以及编码解码,如gzip压缩等)
(5)单独拎出来的缓存问题,HTTP的缓存(这部分包括http缓存头部,ETag,catch-control等)
(6)浏览器接收到HTTP数据包后的解析流程(解析html-词法分析然后解析成dom树、解析css生成css规则树、合并成render树,
然后layout、painting渲染、复合图层的合成、GPU绘制、外链资源的处理、loaded和DOMContentLoaded等)
(7)CSS的可视化格式模型(元素的渲染规则,如包含块,控制框,BFC,IFC等概念)
(8)JS引擎解析过程(JS的解释阶段,预处理阶段,执行阶段生成执行上下文,VO,作用域链、回收机制等等)
(9)其它(可以拓展不同的知识模块,如跨域,web安全,hybrid模式等等内容)
22.display:none 与 visibility:hidden 的区别是什么?
display:none和visibility:hidden都可以实现元素在视窗的不可见,display:none不会保留元素的位置,结构发生了改变,所以触发了回流和重绘;visibility:hidden会保留元素的位置,结构没有发生改变,所以只是触发了重绘。
23.前端路由原理?两种实现方式有什么区别?
前端路由本质就是监听 URL 的变化,然后匹配路由规则,显示相应的页面,并且无须刷新页面。目前前端使用的路由就只有两种实现方式:Hash 模式和History 模式。
Hash 模式
Hash模式会在请求的URL后拼接#,当 # 后面的哈希值发生变化时,可以通过hashchange 事件来监听到 URL 的变化,从而进行跳转页面,并且无论哈希值如何变化,服务端接收到的 URL 请求永远是不包含#的URL。使用window.location.hash可以读取#后的内容。
History 模式
History 模式是 HTML5 新推出的功能,主要使用 history.pushState 和 history.replaceState 来改变URL。通过 History 模式改变 URL 同样不会引起页面的刷新,只会更新浏览器的历史记录。
history.pushState
:在history中新增一条记录,参数有三个。第一个参数是传入的数据,可以为空;第二参数修改的浏览器标题,可以为空;第三个参数是新的URL地址,不可以跨域。
history.replaceState
:在history中修改当前记录,参数和pushState一致。
当用户做出浏览器动作时,比如history.back()、history.forward()、history.go(),会触发 popState 事件,在popState事件里可以拿到路由信息,从而进行页面跳转。
两种模式对比
Hash 模式只可以更改 # 后面的内容,History 模式可以通过 API 设置任意的同源 URL History 模式可以通过API 添加任意类型的数据到历史记录中,Hash 模式只能更改哈希值,也就是字符串 Hash,Hash模式无需后端配置,并且兼容性好。History 模式在用户手动输入地址或者刷新页面的时候会发起 URL 请求,后端需要配置index.html 页面用于匹配不到静态资源的情况
24.重绘和回流
- 回流
当render tree中的一部分(或全部)因为元素的规模尺寸,布局,等改变而需要重新构建。
- 重绘
当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局。
- 区别
回流必将引起重绘,而重绘不一定会引起回流。
- 预防
合并多次对DOM和样式的修改:
累加cssText、className:一次处理掉要添加的样式;
cloneNode :一次把要添加的DOM都克隆好再appened