2020前端面试

https://github.com/haizlin/fe-interview
2、http缓存

  • 强缓存
    强缓存就是给资源设置个过期时间,客户端每次请求资源时都会看是否过期;只有在过期才会去询问服务器。
    不会向服务器发送请求,直接从缓存中读取资源
  • 协商缓存
    请求资源时,服务端和最新资源做对比。
    如果资源没更改,返回304,浏览器读取本地缓存。
    如果资源有更改,返回200,返回最新的资源。
    协商缓存和强缓存使用场景:服务器上的资源会更新,这个时候如果我们还访问本地缓存,那么对用户来说,那就相当于资源没有更新,用户看到的还是旧的资源;所以我们希望服务器上的资源更新了浏览器就请求新的资源,没有更新就使用本地的缓存,以最大程度的减少因网络请求而产生的资源浪费。所以一般会使用协商缓存
  • 本地存储
    本地存储主要有以下几种,localStorage、sessionStorage、cookie、websql、indexDB.
localStorage
在前端设置,可以减少数据请求,长期存储。
sessionStorage
在前端设置,只存在当前会话中即重新打开浏览器则数据消失
cookie
在后端设置,保存在客户端本地文件,通过set-cookie设置且Cookie的内容自动在请求的时候被传递到服务器
3、nginx负载均衡 使用upstream设置不同的服务器,以便每次访问的时候,都会访问到不同的服务器

2020前端面试
文章图片
image.png 5、key使用index会有什么问题 key是这条数据唯一的标识,用来追踪列表中哪条元素进行变动了。如果数组某项数据删除,以前的数据和重新渲染后的数据随着 key 值的变化从而没法建立关联关系. 这就失去了 key 值存在的意义,可能就会导致数据错乱。一般都会使用每条数据的id,因为id是唯一的
6、css优先级 内联样式>ID选择器>类选择器(Class)
8、绝对定位和相对定位的区别 绝对定位:是相对于元素最近的已定位的祖先元素,如果元素没有已定位的祖先元素,那么它的位置则是相对于body
相对定位:相对于元素在文档中的初始位置
9、let、const、var的区别 const一般用于声明常量,var和let一般用于声明变量
const和let不能重复定义属性名,而var可以,并且var存在变量提升的现象
var可以跨快访问
10、get和post的区别 get返回时,不会重新请求,而post返回时,会重新提交表单
get没有post安全,因为get请求参数直接暴露在url上
get参数通过url传递,post放在body中
get请求参数长度有限制,post没有
get请求参数会被保存在浏览器历史中,而post不会
11、常用状态码 200 - 成功
301 - 重定向
304 - 一般用于协商缓存,向后台发请求读取资源,如果本地有缓存,则返回304读取本地缓存
400 - 前台数据格式有错误
401 - 权限不足
403 - 服务器拒绝请求
500 - 服务器内部错误
503 - 服务器维护
12、react调用setState后发生了什么 react会触发调和过程,react会以相对高效的方式根据新的状态构建react元素树并且重新渲染界面,react会自动计算新数树与旧树的差异,然后根据差异来渲染。
14、react为什么虚拟 dom 会提高性能? 虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能。传统diff算法复杂度达到 O(n^3) ,n是树的节点数,而虚拟dom中的Diff算法复杂度只需要O(n)复杂度
15、了解redux吗? redux是公共管理状态的,主要有三个核心方法,action,reducer,store,工作流程就是view调用dispatch触发action,action可以写异步操作,然后分发dispatch,reducer会根据action分发的dispatch中的type和state来更新状态。当我们在组件中使用则需要使用connect将组件与store连接起来。
16、JS事件循环 首先JS是单线程的,一般的代码都会按顺序执行,如果遇到异步代码,会将异步代码放到另一个线程,这个线程我们叫工作线程,主线程继续执行剩余的代码,当工作线程异步代码执行完成过后,比如setTimeout时间到了或者axios得到了数据,该线程就会将回调函数放到消息队列里面去,当主线程代码执行完过后,会检查任务队列是否有任务要执行,如果有,则会执行,如果没有,则会一直循环等待任务到来。
17、什么是闭包和内存泄漏 闭包通俗来讲,就是a函数里面还有b函数,而b函数可以访问a函数里面的变量。
因为闭包会携带它的函数的作用域,这样会导致多余的内存被占用,这就是内存泄漏
在推出函数之前,将变量赋值为null,就可解决内存泄漏
18、async和await的原理和使用 在异步代码的函数上加上async,在异步代码前加上await,这样使用的话,我们即使调用的异步代码,也会变成类似于同步,只有让这个异步代码执行完过后,才会执行下面的代码,好处就是promise一般会通过then方法来获取异步数据,如果过多的话,就会造成回调地狱,代码可读性差,使用async/await可以使代码很简洁。
19、MVVM是什么? MVVM即Model-View-ViewModel的简写。模型(Model)指的是后端传递的数据。视图(View)指的是所看到的页面。视图模型(ViewModel)是mvvm模式的核心,它是连接view和model的桥梁。例如react的state和vue的data里面,然后页面数据是从这个state或data里面取到的
20、css和less区别 less是css预处理语言,扩展了css。
  • less可以声明变量,@color: #4D926F;
  • less可以混合,即b样式可以直接调用a样式
21、form表单提交和ajax提交表单区别
  • ajax是异步的,网页不需要刷新,form表单提交则需要刷新
  • ajax提交是在后台新建请求,form表单则是趋势放弃本页面,再申请
22、Promise是什么? promise是一个对象,内部有三个状态,resolved,rejected,pending。当我们new一个promise对象的时候,会传入一个回调函数,这回调函数有resolve和reject两个方法。想改变状态只能调用resolve()或者reject()这两个方法,并且resolve可以将异步数据存储在内部data里面,然后他们通过.then方法来获取数据,then方法可以接受两个参数,一个成功的回调,一个失败的回调。但是我们获取数据一般是通过async/await来获取数据。这样可以避免回调地狱。
23、高阶函数是什么? 高阶函数就是指函数作为可以作为另外一个函数的参数
24、组件化开发有什么好处?
  • 可组合:便于将复杂的UI拆分成多个简单的UI组件
  • 可复用:每个组件都具有独立功能,可使用在多个场景
  • 便于维护:每个组件都有自己的功能,便于开发者维护
25、什么是跨域? 当一个url的协议、域名、端口三者之间任意一个与当前url不同即为跨域,跨域则是因为受到浏览器同源策略的限制,同源就是指两个页面具有相同的协议、域名、端口号。
26、怎么解决跨域?
  • 1、nginx反向代理
  • 2、jsonp请求,但是只能处理get请求
  • 3、CORS跨域
    cors全称是跨域资源共享,cors需要浏览器和服务器同时支持,浏览器会将请求分为两大类,一类是简单请求,一类是复杂请求.
  • 简单请求一般就是get,post,并且头部信息也不能带多余的参数,当浏览器发现是简单请求时,请求头会多一个字段origin,origin会指出当前请求属于哪个域,服务器会根据这个值决定是否允许跨域。
  • 特殊请求,例如put,delete等,则会在发送请求之前先发送一个预检测请求,服务器收到预检测请求,如果允许跨域,客户端则能成功发送请求
27、react框架的优点 1、react速度快,因为含有虚拟dom
2、组件化,便于维护
3、单向数据流,便于阅读代码
4、纯粹的javaScript语法,没有任何专有的react语法
28、vue框架和react框架的区别
  • vue使用html模板进行渲染,只是在html上多了一些特有的属性,例如v-for,v-if等,而react则是使用jsx语法,jsx语法则是可以再javaScript中写html
29、什么是回调函数? 回调函数则是函数作为参数传入另外一个函数,这个作为参数的函数会在某个时机被调用,这就是回调函数
30、xss跨站脚本如何进行?防御手段? 如何进行:xss是指恶意攻击者利用网站没有对用户提交的数据进行过滤处理,进而添加一些恶意代码,嵌入到Web页面,从而利用用户的身份进行某种动作
防御手段:不信任客户端提交的任何数据,只要是客户端提交的就应该先进行对应的过滤处理。
31、CSRF跨站请求伪造如何进行?防御手段? 如何进行:当用户在某网页登录后,在没有关闭网页的情况下,收到恶意链接,点击链接,则会利用浏览器的cookie把密码改掉。
防御手段:后端使用jwt技术验证token,使用axios请求
32、web上传漏洞如何进行?防御手段? 如何进行:用户上传了一个可执行的脚本文件,并通过脚本文件获得了执行服务器端命令的能力
防御手段:1、前后端都对文件后缀名进行限制
2、吧文件上传目录的权限设置为只读
33、什么是盒子模型? 盒子模型从外到内由margin、border、padding、content组成
34、简要说一下css的元素分类 块级元素:div,p,h1,form,ul,li;
行内元素 : span,a,label,input,img,strong,em;
35、axios有什么好处?
  • 支持promise语法
  • 拦截请求头和响应
  • 自动转换json数据
  • 客户端支持防止csrf
36、冒泡排序 比较相邻的元素,如果前者比后者大,则交换,大的在右边,双重循环,最外层循环arr.length - 1,内层循环比较相邻两个数的大小,直到吧最大的数放在最右边,外层循环arr.length-1次,然后数组就会从小到大排列。
37、快排排序 一个数组里面寻找中间的值作为基准,然后创建两个空数组,循环原数组,将数组的每个值跟基准比较,比基准小的存在一个数组,比基准大的存在一个数组,然后递归执行以上操作,最后将两个数组合并。
38、为什么要清楚浮动,如何清除? 当给元素设置了浮动float过后,就会产生高度塌陷的情况,就是如果子元素高度大于父元素时,父元素就包含不住子元素了。
  • 给父元素添加伪元素清楚浮动
.clear-float:after{ display:block; content : ""; clear:both; height:0 }

  • 父级盒子触发BFC
39、实现数组去重
  • 使用indexOf()去重,首先创建一个空数组,然后原数组循环遍历,然后判断如果当前的这个值在创建的新数组里面没有,也就是等于-1,那么就添加,如果有,则不添加。
let res = [] for (let i = 0; i < arr.length; i++) { if (res.indexOf(arr[i]) === -1) { res.push(arr[i]) } }

  • 使用ES6,Set去重
const arr = [1,2,2,3,4,5,3] console.log(new Set(arr))

40、谈一谈箭头函数
  • 箭头函数可以更改this的指向,使this指向上下文
  • 箭头函数后面只要一条语句时,可以直接写在后面
  • 箭头函数需要返回一个对象时,则需要使用({})
41、谈一谈ES6中的模块化 ES6的模块化分为导出(export)与导入(import)两个模块。如果希望外部能读取模块当中的内容,就必须使用export暴露出去,然后在另外一个文件中用Import引入该模块,一个模块如果只有一个默认导出的话,就使用export default,引入的时候也可使用as进行重命名。
42、JS原型链和原型
  • prototype是函数才有的属性
  • __proto __是每个对象都有的属性
    当我们定义一个函数的时候,就会产生一个原型对象,当我们使用这个函数构造对象,该对象都会从原型对象中继承属性、方法。
    当JS寻找该对象的属性时,先会查找对象本身是否存在该属性,如果不存在,则会在原型链上查找。
    因为任何对象都有proto,所以会形成一个链条,当我们到顶点的时候,就会发现proto里面只有object了,因为JS中任何对象都是Object的实例。
43、使用原型链实现js继承
  • 思路就是让子类的原型等于父类的实例,因为父类的实例,就继承了父类的属性和方法,然后父类的属性和方法就定义在子类的原型对象上,这样子类就实现了继承父类
//父方法 function SupperFunction(flag1){ this.flag1 = flag1; }//子方法 function SubFunction(flag2){ this.flag2 = flag2; }//父实例 var superInstance = new SupperFunction(true); //子继承父 SubFunction.prototype = superInstance; //子实例 var subInstance = new SubFunction(false); //子调用自己和父的属性 console.log(subInstance.flag1); console.log(subInstance.flag2);

44、Vue组件间的通信
  • 通常父组件传递给子组件使用props
  • 子组件传递给父组件,使用ref属性,获取真实dom
  • 子组件使用emit方法
  • 使用vux
45、介绍Vuex vuex能对vue项目进行状态管理,主要一般通过state,mutations,action这三个模块构造,state是保存所有数据,mutations用来保存所有方法,用来改变state的数据,action一般暴露给用户使用,可执行异步操作,用来触发mutatios的方法,用来改变数据。一般在页面中通过mapState来读取数据,通过mapActions来操作action。面对复杂的应用我们还需要创建modules,将vuex的store对象拆分成模块来写。
46、vuex的优缺点 优点首先是
  • 代码看得更简洁了,我们阅读代码时,不需要去看组件之间如何传递数据的,特别是非父子组件传递
  • 减少了ajax请求,可以从store里面直接取
    缺点:
  • 每次刷新vuex也就会刷新,但是我一般需要长久存储的数据,我会存储在localStorage里面,然后vuex再读取。
47、vue双向数据绑定原理 实现双向数据绑定主要是结合发布者-订阅者的模式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发给订阅者,触发相应的监听回调,当把一个普通的对象作为data选项时,vue将遍历它的属性并且转换为getter/setter。
48、sum求和,可以传入多个参数 使用arguments这个API,arguments为函数传入的实参,并且会转换为数组形式,这样的话就好做了,遍历实参,相加,最后返回。
49、多维数组降为一维数组 将数组转换为字符串,再切割字符串
let arr = [1, 2, 3, 4, 5, [6, 7, 8, [9, 10, 11, 12, [13, 14, 15, 16]]]] console.log(arr.toString()) let newArr = arr.toString().split(',') console.log(newArr)

50、什么是TCP OSI一共有7层网络模型,应用层、表示层、会话层、传输层、网络层、数据链路层、物理层,TCP和UDP是传输层的协议。
TCP无论哪一方向另一方发送数据之前,都会在双方之间建立一条连接。连接是通过“三次握手”进行初始化的。三次握手的目的是建立可靠的通信连接,确认双方的发送与接收是否正常。完成了三次握手,客户端和服务端就可以开始传送数据了。
三次握手的步骤
  • 第一次握手,客户端发送请求建立连接,请求报文段
  • 第二次握手,服务器收到请求,发送同意并请求与客户端建立连接
  • 第三次握手,客户端收到请求,发送同意与服务器建立连接
    当客户端与服务器通过三次握手建立了TCP连接过后,当数据传送完毕,相应的就要断开TCP连接了,于是就有了四次分手的步骤。
    四次分手的步骤
  • 第一次分手,客户端发送断开请求
  • 第二次分手,服务器收到断开请求,发送同意断开连接的请求
  • 第三次分手,服务器发送请求断开连接
  • 第四次分手,客户端收到,发送同意断开连接
51、为什么TCP是三次握手,而不是两次 可能会形成死锁。假设客户端给服务器发送了一个连接请求报文,服务端成功接收并给客户端发送了确认应答报文,此时服务端并不能确认该应答报文是否成功到了客户端,但因为两次握手,所以这时候服务端就处于成功连接的状态了,并给客户端发送数据。如果客户端未收到服务端的应答报文,则不知道服务器是否确认好建立连接,甚至不知道自己发送给服务器的报文是否成功抵达,此时客户端会认为连接并未成功建立,会忽略服务端发送过来的任何数据。而服务端发送的数据未得到相应超时时,会重复发送同样的数据,这样就形成了死锁。
52、TCP和UDP的区别 TCP是一种面向连接,可靠稳定的传输协议,建立连接需要经历三次握手,握手成功才可通信,但是速度比较慢,效率比较低,容易被DOS,DDOS攻击。
UDP是一种面向无连接,不可靠的传输协议,会直接建立连接,速度快,没有三次握手的机制,所以会相对安全,但是UDP还是可能会被flood攻击,在网络不好的情况,容易发生丢包。
  • 当对网络通信质量有要求时,比如:整个数据要准确无误的传递给对方,这往往对于一些要求可靠的应用,比如HTTP,HTTPS,FTP等传输文件的协议,POP,SMTP等邮件的传输协议。常见使用TCP协议的应用:
    1.浏览器使用的:HTTP
    2.FlashFXP:FTP
    3.Outlook:POP,SMTP
    4.QQ文件传输
    UDP 文件传输协议
  • 对当前网络通讯质量要求不高的时候,要求网络通讯速度尽量的快,这时就使用UDP
    日常生活中常见使用UDP协议:
    1.QQ语音
    2.QQ视频
HTTP请求报文 HTTP的请求报文包括:请求行(request line)、请求头部(header)、空行 和 请求数据(request data) 四个部分组成。
  • 请求行包括: 请求方法,URL(包括参数信息),协议版本这些信息
  • 请求头部(Header)
  • 空行(CR+LF):请求报文用空行表示header和请求数据的分隔
  • 请求数据:GET方法没有携带数据, POST方法会携带一个body
浏览器渲染的步骤
  • 处理HTML标记并构建DOM树
  • 处理CSS标记并构建CSSOM树
  • 将DOM与CSSOM合并成一个渲染树
  • 根据渲染树来布局,计算每个节点的布局信息
  • 将各个节点绘制到屏幕上
53、输入url后发生了什么
  • 用户输入url通过DNS解析为对应的IP地址
  • TCP连接
  • 发送http请求
  • 返回http响应
  • 浏览器解析渲染页面
  • 断开TCP连接
54、重绘和重排的区别 重绘不一定重排,重排必定导致重绘
  • 重绘:指一个元素外观被改变,浏览器会根据元素新属性重新绘制,使元素呈现新的外观,比如改变某个元素的背景色、文字颜色、边框颜色等
  • 重排 :当渲染树的一部分更新并且节点的尺寸发生了变化,浏览器会使渲染树种受到影响的部分失效,并且重新构造渲染树。
    引发重排:
    1、添加、删除可见的dom
    2、元素的位置改变
    3、元素的尺寸改变
    4、页面渲染初始化
    5、浏览器窗口尺寸改变
    优化
    浏览器会维护一个队列,把所有引起重拍、重绘的操作放入这个队列,等队列到了一定的数量或者到了一定的时间间隔,浏览器就会进行处理,这样多次重排重绘就会进行成一次重排重绘
  • 不要一条一条修改dom样式,写在定义好css的class中
  • 为动画元件使用绝对定位,修改样式就不会进行重绘
54、HTML行内元素、块状元素、行内块状元素的区别 使用display可以将三者任意转换,
  • 行内元素,最常用的就是span
    (1)、设置宽高无效
    (2)、margin仅左右有效
    (3)、不会自动换行
  • 块状元素,具有代表性的就是div
    (1)、能够识别宽高
    (2)、margin和padding均有效
    (3)、可以自动换行
  • 行内块状元素,
    (1)、能够识别宽高
    (2)、不会自动换行
    (3)、默认排列方式从左到右
55、http和https的区别 https的ssl加密是在传输层实现的
  • http传输的数据都是未加密的,而https是通过ssl协议对数据进行加密处理
  • https协议需要ca证书,费用较高
  • http协议的端口为80,而https协议端口为443
56、移动端怎么做适配的
  • 使用viewport,随着屏幕宽度变化,页面也会跟着变化

width设置成了设备的宽度,initial-scale控制了页面加载时候的缩放等级,maximum-scale为用户最大缩放值,user-scalabel是否允许用户进行缩放
57、box-sizing属性 box-sizing是更改盒子模型基准,有两个选项,一个是content-box,一个是border-box。还有一个是inherit默认的是content-box。
其实两者的区别也就是盒子的宽高是否包含border和padding,如果是content-box那么宽高就是固定的,如果是border-box,那么宽高就是设定的宽高再减去border和padding,就是这个盒子的宽高。
inherit是继承父元素的box-sizing。
58、宏任务与微任务 宏任务例如,script,setTimeout,setInterval
微任务例如Promise.then
执行一个宏任务,执行过程中如果遇到微任务,就会将微任务添加到微任务的队列,宏任务执行完毕过后,会立即按顺序执行微任务,当这个宏任务执行完毕后,开始进行渲染,渲染完毕后,开始下一个宏任务。
59、BFC是什么? BFC是块级格式化上下文,是用于布局块级盒子的一块渲染区域。
一般触发BFC的条件
  • 根元素,即html元素
  • float的值不为none
  • overflow的值为hideen
  • display的值为inline-block
  • position的值为absolute或者fixed
    作用
  • 可以阻止元素被浮动的元素覆盖
  • 清除浮动
  • 解决同一个BFC区域的垂直方向margin塌陷的问题
    属于同一个BFC的两个相邻的box的margin会重叠,以大的为主。要想解决这个问题,可以将两个盒子分为不同的BFC中。
60、AST抽象语法树 抽象语法树,是源代码的抽象语法结构的树状表现形式,一般指编程语言的源代码
61、put、post、patch的区别 post用来创建资源,多次执行,会导致多条资源重复创建
put一般用来更新已知资源
patch对已知资源进行局部更新
62、vue-router原理 vue-router是应用在单页面应用中。
单页面:第一次进入页面的时候会请求一个html文件,当url变化时,js会感知到,js会将当前的页面清除掉,判断当前url需要显示哪个组件,清除不需要的,显示需要的组件。
实现原理:更新视图但不重新请求页面
前端路由主要有两种模式,hash模式和history模式,hash会在域名后面加一个#号,hash虽然会出现在url中,但不会包括在http请求中而history则不存在,没有#号,这种模式需要服务端支持。服务端接收到请求后,都指向同一个html文件。
vue-router也是利用了这两个特性来实现前端路由
63、Node.js中间件 中间件主要是指封装所有http请求细节处理的方法,比如记录日志、权限验证、异常处理等。
中间件是从http请求发起到响应结束过程中的处理方法,通常需要对请求和响应进行处理。
64、什么是DNS、FTP,基于什么协议? DNS(Domain Name System):域名解析协议,端口号:53;通过域名解析获得域名所对应的IP
FTP(File Transfer Protocol):文件传输协议,端口号:21;用户可通过客户机程序向远程主机上传文件;或从远程主机上下载文件。
  • FTP用的TCP协议。
  • DNS域名解析时用的UDP协议,DNS区域传输的时候使用的TCP协议。
    辅域名服务器会定时(一般3小时)向主域名服务器进行查询以便了解数据是否有变动,这就是区域传输。
65、Vue生命周期 beforeCreate : 组件创建之前
created:组件创建后
beforeMount:组件挂载之前
mounted:挂载完成
beforeUpdate:数据更新前
updated:数据更新后
beforeDestory:实例销毁之前
destored:实例销毁后
65、防抖和节流 防抖:让某个时间期限内,事件处理函数只执行一次,例如获取滚动条位置,就要每3S执行一次,可以使用定时器来实现,我们可以在一个方法里面使用闭包来存储一个状态,定时器每次执行,都会返回一个类似于ID,ID是用来关闭定时器的,每次执行该方法,如果有ID就清除该ID的定时器,并且创建一个新的定时器。
function dbbounce(fn,delay){ let timer = null return function(){ //setTimeout每次执行,会返回给我一个特殊的值,这个值是用来关闭定时器的,每次执行该方法时,如果有timer就清楚上个定时器 //如果没有就执行定时器 if(timer){ clearTimeout(timer) } timer = setTimeout(fn,delay) } }function showTop (){ var scrollTop = document.documentElement.scrollTop console.log('滚动距离',scrollTop) }window.onscroll = dbbounce(showTop,3000)

节流:函数执行一次后,在某个时间段内暂时失效,过段时间再重新激活,使用闭包存储一个布尔类型的状态,每次执行该方法时,如果状态为false则不执行,如果状态为true,则会使状态先等于false,达到冷却的效果,再调用定时器,定时器完成过后,会将状态改为true。
function throttle(fn, delay) { let valid = true return function () { //类似于技能能却,执行完一次,有间隔时间,时间走完了,才能再执行 //滚动时,如果状态为false就不执行,如果状态为true,在间隔期间设置状态为false,然后在执行定时器,定时器执行完,将状态改为true if (!valid) { return false } valid = false setTimeout(() => { fn() valid = true }, delay)} }function showTop() { var scrollTop = document.documentElement.scrollTop console.log('滚动距离', scrollTop) }window.onscroll = throttle(showTop, 2000)

66、ajax,axios和fetch有什么区别 ajax
  • 本身针对MVC的编程,不符合现在MVVM的框架
  • JQuery整个项目太大,单纯使用ajax却要引入整个JQuery
    axios
  • 支持Promise语法
  • 客户端支持防止CSRF
  • 拦截请求头和响应
  • 自动转换json数据
    fetch
  • fetch只对网络请求报错,对400,500都当做成功的请求,需要封装去处理。
67、为什么JS是单线程的? JS作为浏览器脚本语言,JS的主要用途是与用户互动,以及操作DOM。这决定了只能是单线程,否则会带来复杂的同步问题,比如,假如JS有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时候浏览器就不知道应该以哪个为准。
68、路由懒加载 路由懒加载也叫按需加载,即在需要的时候进行加载,单页应用,利用webpack打包后的文件会非常大,造成进入首页时,需要加载的内容过多,时间过长,会出现长时间白屏,而运用懒加载可以将页面进行划分,需要的时候加载页面,减少首页加载用时。
routes: [ { path: "/", name: "home", component: Home }, { path: "/about", name: "about", component: () => import(/* webpackChunkName: "about" */ "./views/About.vue") } ]

69、前端项目优化
  • 路由懒加载
  • 开启nginx的gzip压缩
  • 抽取公用组件和方法,清除冗余代码
  • 使用压缩工具压缩图片,例如tinypng
72、水平垂直居中
  • flex布局, justify-content: center; align-items: center;
  • 给父元素设置相对定位,给子元素设置绝对定位
#father { width: 500px; height: 300px; background-color: skyblue; position: relative; } #son { background-color: green; position: absolute; left: 50%; top: 50%; transform: translateX(-50%) translateY(-50%); }

73、两个等号和三个等号的区别
  • 三个等号称为等同符,当两边值类型相同时,直接比较值,若类型不相同,直接返回false
  • 两个等号称为等值符,当等号两边类型相同时,直接比较值,若不相同,则先转化为类型相同的值,在进行比较。
    类型转换规则:
    (1)如果等号两边是boolean、string、number三者中任意两者进行比较时,优先转换为数字进行比较。
    (2)如果等号两边出现了null或undefined,null和undefined除了和自己相等,就彼此相等
74、常用操作字符串方法
  • split(sep,limit):将字符串分割为字符数组,limit为从头开始执行分割的最大数量
  • slice(start,end):返回字符索引在start和end(不含)之间的子串
  • substr(start,length):从字符索引start的位置开始,返回长度为length的子串
  • substring(from,to):返回字符索引在from和to(不含)之间的子串
  • charAt(index):返回指定索引处的字符串
  • charCodeAt(index):返回指定索引处的字符的Unicode的值
  • lastIndexOf(str):返回str在父串中最后一次出现的位置,若没有则返回-1
  • indexOf(str):返回str在父串中第一次出现的位置,若没有则返回-1
75、常用操作数组方法
  • push(),向数组的末尾添加元素
  • pop(),删除数组中最后一个元素
  • unshift(),向数组开头添加元素
  • shift(),删除数组第一个元素
  • splice(index,howmany,item1....):添加/删除数组元素,index规定位置,howmany为删除的数量,item1......可选向数组添加的新项目
  • sort(),对数组元素进行排序,并返回这个数组,sort的比较函数有两个参数,返回a-b则使升序,返回b-a则是降序
  • slice(start,end):返回数组下标在start和end(不含)之间的值
  • indexOf() 查找数组是否存在某个元素,返回下标
  • lastIndexOf() 查找指定元素在数组中的最后一个位置
  • includes() 查找数组是否包含某个元素 返回布尔
  • filter(function) 过滤原始数组,返回新数组
    function(currentValue,index,arr): 数组中每个元素需要调用的函数。
    // 回调函数的参数
  1. currentValue(必须),数组当前元素的值
  2. index(可选), 当前元素的索引值
  3. arr(可选),数组对象本身
76、什么是事件委托 事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
当我们有很多dom需要添加处理事件,比如ul下面有很多li,我们给每个li都要添加相同的点击事件,通常会用for循环,给它们添加点击事件,这有很大的性能弊端
77、call、bind、apply的区别?
  • bind 返回一个函数, 第一个参数是改变this指向的对象 直接传参
  • apply 对函数的直接调用, 第一个参数是改变this指向的对象 参数用数组包裹
  • call 对函数直接调用,第一个参数是改变this指向的对象 直接传参
78、深拷贝和浅拷贝的区别 它们最根本的区别在于是否真正获取了一个对象的复制实体,而不是引用
浅拷贝现在可以使用Object.assign快速实现
Object.assign()只有源对象,没有目标对象时为浅拷贝
JSON.parse(JSON.stringify())可以实现深拷贝
79、JSON.parse和JSON.stringify的区别
  • JSON.parse()【从一个字符串中解析出json对象】
  • JSON.stringify()【从一个对象中解析出字符串】
80、JS动画和CSS3动画差异性 css3后来添加了transform动画函数
css3动画与js动画的区别:
js功能涵盖面比css3广
css3比js更易实现
css3存在兼容问题 js不存在兼容问题
81、join("")和toString()的区别 join(“”)转换为字符串时,会将逗号去掉
82、JS基本数据类型 基础类型:Undefined,Null,Boolean,Number,String,Symbol
引用类型:Object,Array
symbol生成的是一个全局唯一的值,Symbol(1) === Symbol(1)是为false的。
83、ES6新特性
  • promise
  • async/await
  • class
  • 箭头函数
  • 扩展运算符
84、谈谈ES6中的class 首先class是用来创建类的,在传统的js中,没有类的概念。class的作用让原型对象的写法更加清晰
  • 首先我们在类里面写方法时,方法时直接定义在原型对象上面
  • constructor就相当于构造函数,接受参数
  • 类必须使用new调用
85、扩展运算符 【2020前端面试】扩展运算符就是遍历目标对象,拷贝到当前对象中
扩展运算符如果目标对象中含有引用数据类型,则使用扩展运算符拷贝出来的则是浅拷贝。
86、vue和react的事件绑定对比 首先vue的特色是双向绑定,而react是单向绑定,其实vue的双向绑定也可以使用单向绑定加上onChange事件监听来实现。
87、Hooks是什么 原来我们写一个组件需要去声明一个类,但是使用了hooks就不需要了,就直接使用function创建一个函数,然后使用useState来管理状态,然后在返回html模板就可以成功创建一个组件了
88、webpack是什么,loader是什么? webpack是前端构建的一个工具,loader其实就是提供了打包方案,就比如webpack不知道怎么打包图片模块、css模块、js模块时,就会使用各种loader来帮助Webpack打包
比如:
image-loader:加载并且压缩图片文件
babel-loader:把 ES6 转换成 ES5
css-loader:加载 CSS,支持模块化、压缩、文件导入等特性
eslint-loader:通过 ESLint 检查 JavaScript 代码
plugin其实主要是监听一些webpack事件的,然后做优化
89、CSS可继承的属性 1、字体系列属性,例如字体粗细,风格,大小
2、文本系列属性,例如行高,文本颜色
无继承的属性:display,背景属性,盒子模型的属性,定位属性
谈一谈RCM自动升级这个项目? 公司每次有升级包,就需要在这创建任务,上传升级包,然后对任务可视化操作,显示进度和状态信息等,可以编辑,可以查看详情,可以下载对比文件等,除此之外还有一些基准文件配置、邮箱配置、常用工具等功能。
1、表单联动太多,开始想着用change方法来监听数据,最后编辑的时候,因为需要初始化数据,最后才采用的watch的深度监听
2、formdata传递数组,当时后端需求就是我需要传一个数组,这个数组每一个对象里面都包含的有文件,所以我选择采
用Formdata形式传递数据给后台,而formdata添加数据又是key,value的形式,所以我添加时key就是将数组转为语义化来命名。
3、下载浏览器默认打开的文件。
谈一谈你做项目遇到的困难 1、最开始做项目的时候,跨域问题以及服务器配置
2、前期对数据的处理,例如数组,或者对象类型的方法了解的太少

    推荐阅读