前端面试题整理(持续更新...)
# 整理了一些前端面试题供大家在这疫情之下也能找到心仪的工作,大家一起努力!!!
1,vue双向绑定原理
答:vue数据双向绑定是通过对数据的劫持,结合发布、订阅的模式来实现的,
延伸1:双向绑定核心方法是Object.defineProperty() 方法
延伸2:核心方法的理解,Object.defineProperty(obj,prop,descriptor)语法内有三个参数
obj:要定义其上属性的对象
prop:要定义或修改的属性
descriptor:具体的改变方法
简单的说 就是用这个方法来定义一个值。当调用时我们使用了它里面的get方法,当我们给这个属性赋值的时候,又用到了它里面的set方法
2,vue的⽣命周期有哪些
答:vue生命周期有11个。8个常见的阶段:1、beforeCreate(创建前);2、created(创建后); 3、beforeMount(载入前);4、mounted(载入后);5、beforeUpdate(更新前);6、updated(更新后);7、beforeDestroy(销毁前);8、destroyed(销毁后);后三个不常用阶段:;9、activated;10、deactivated;11、errorCaptured。
3,v-if 和v-show有什么区别?
答:v-if控制的是元素的加载与销毁,v-show控制元素的display样式;
区别:1. v-show 只是简单的控制元素的 display 属性,而 v-if 才是条件渲染(条件为真,元素将会被渲染,条件 为假,元素会被销毁);
2. v-show 有更高的首次渲染开销,而 v-if 的首次渲染开销要小的多;
3. v-if 有更高的切换开销,v-show 切换开销小;
4. v-if 有配套的 v-else-if 和 v-else,而 v-show 没有
5. v-if 可以搭配 template 使用,而 v-show 不行,v-show 是通过 display 来控制标签进行渲染的,但是 template 标签在 vue 解析后是不会显示在页面上的,是虚拟 Dom,所以无法使用 v-show。
4,async await 是什么?它有哪些作⽤?
答:async await是 JS 中编写异步或非阻塞代码的新方法,它基于 Promise,并与所有现存的基于Promise 的 API 兼容。在async/await,我们使用 tru/catch 语法来捕获异常。
5,什么是原型链?
答:每个原型对象中都有 prototype 属性,指向一个对象,这个对象就叫做原型或者原型对象
每个对象都有 __proto__ ,指向构造函数的原型对象,层层递进到 null 为止
6,什么是闭包?闭包有哪些优缺点?
答:想重用变量又想保护这个变量不被篡改的一种机制,是指有权访问另一个函数作用域中的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量.
闭包的优点是:
1.变量被保存起来没有被销毁,随时可以被调用
2.只有函数内部的子函数才能读取局部变量,可以避免全局污染
缺点是:如果闭包使用不当,就会导致变量不会被垃圾回收机制回收,造成内存泄露
7,es6有哪些新特性?
答:1、向对象添加属性;2、合并对象;3、删除对象的属性;4、动态删除属性;5、调整对象属性的位置;6、默认属性;7、重命名对象的属性;8、条件属性。
8,v-for 循环为什么⼀定要绑定key ?
答:使用v-for更新已渲染的元素列表时,默认用就地复用策略;列表数据修改的时候,他会根据key值去判断某个值是否修改,如果修改,则重新渲染这一项,否则复用之前的元素;(大白话:解决复用问题)
9,组件中的data为什么要定义成⼀个函数⽽不是⼀个对象?
答:组件是可复用的vue实例,一个组件被创建好之后,就可能被用在各个地方,而组件不管被复用了多少次,组件中的data数据都应该是相互隔离,互不影响的。
10,什么是symbol
答:Symbol 是 ECMAScript 2015 中新添加的特性,生成一个唯一标识符,可用于属性名称、也可用于属性值。目的是消除属性名称冲突。
11,什么是同源策略
答: 同源策略就是浏览器的一个安全限制,它阻止了不同【域】之间进行的数据交互
12,什么是递归,递归有哪些优缺点?
答:如果一个函数在内部可以调用其本身,那么这个函数就是递归函数。
优点:结构清晰、可读性强
缺点:效率低、调用栈可能会溢出,其实每一次函数调用会在内存栈中分配空间,而每个进程的栈的容量是有限的,当调用的层次太多时,就会超出栈的容量,从而导致栈溢出。
13,let和const 的区别是什么?
答:let声明的变量可以改变,值和类型都可以改变;而const声明的常量不可以改变,这意味着,const一旦声明,就必须立即初始化,不能以后再赋值。
14,vue性能优化
答: 1,代码模块化,咱们可以把很多常用的地方封装成单独的组件,在需要用到的地方引用
2,for循环设置key值,在用v-for进行数据遍历渲染的时候,为每一项都设置唯一的key值,为了让Vue内部核心代码能更快地找到该条数据,当旧值和新值去对比的时候,可以更快的定位到diff。
3,Vue路由设置成懒加载,当首屏渲染的时候,能够加快渲染速度
4,可以使用keep-alive,keep-alive是Vue提供的一个比较抽象的组件,用来对组件进行缓存,从而节省性能。
5,修改vue.config.js中的配置项,把productionSourceMap设置为false,不然最终打包过后会生成一些map文件,如果不关掉,生成环境是可以通过map去查看源码的,并且可以开启gzip压缩,使打包过后体积变小
6,第三方模块按需引入
15,路由模式:hash和history
答:hash:
1,hash模式下地址栏中带#,路由地址就是#后面的内容,切换路由,变化的是#后面的内容
2,hash模式下url变化是通过浏览器的hashchange方法监听的
3,hash的兼容性更好,甚至能兼容低版本的ie浏览器
4,hash模式下路由改变后手动刷新页面不会报错(404),因为hash模式请求页面的地址永远是# 前面的内容,所以总是能请求成功,得到index.html页面,再通过路由渲染显示对应得组件
history:
1,history模式下地址栏中没有#,从视觉上更加美观
2,history路由的实现主要依赖于html5提供的history全局对象,这个全局对象暴露了一些有用的方法:
3,history模式下手动刷新页面出现404错误的原因:因为history模式请求页面的地址是地址栏里面全部的内容
16,== 和 ===的区别
答:两者都是判断等式两边是否相等,最大的区别就是==会进行类型的转换之后再判断两者是否相等,而===不会进行数据类型的转换,先判断两边的数据类型是否相等,如果数据类型相等的话才会进行接下来的判断,再进行等式两边值得判断,可以理解为只有等式两边是全等(数据类型相同,值相同)的时候结果才会是true,否则全为false。
17,说说严格模式
答:严格模式是ES5引入的,不属于ES6,ES6自动采用严格模式
严格模式的限制
1,没有变量提升,变量必须先声明在使用
2,不能重复声明
3,argument不会自动反应函数参数的变化
4,eval不会在其外层作用域中引入变量
5,禁止this指向全局变量
6,增加了保留字(比如protected、static和interface)
三不能
1,不能使用with语句
2,不能使用前缀0表示八进制数,否则会抱错
3,不能删除变量,只能删除属性
严格模式的优点:
1,消除js语法的不合理性
2,消除代码运行的不安全性
3,提高运行效率
18,TCP和UDP区别
答:UDP协议旨在ip数据报的服务之上增加了很少的功能,即复用分用和差错检测功能,连接管理(三次握手,四次挥手)
主要特点是:
1,UDP是无连接的,减少开销和发送数据之前的时延
2,UDP使用最大努力交付,即不保证可靠交付
3,UDP是面向报文的,适合一次性传输少量的数据网络应用。
4,UDP无拥塞控制,适合很多的实时应用
tcp协议的特点
1,tcp是面向连接(虚连接)的传输层协议
2,每一条TCP连接只能由两个端点,每一个tcp连接只能是点对点的
3,tcp提供可靠的交付服务,无差错,不丢失,不重复,按序到达(可靠有序,不重不丢)
4,tcp提供全双工通信
19,Vuex
答:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
20,什么是防抖和节流,js 如何处理防抖和节流
答: 当持续触发事件时,保证只执行最后一次事件处理函数。简单来说:用一个性定时器来延缓运行。
当持续触发事件时,保证一定事件段内只调用一次事情处理函数
防抖在连续的事件,只需触发一次回调的场景有:
1,搜索框搜索输入。只需用户最后一次输入完,再发送请求手机号、邮箱验证输入检测
2,窗口大小resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。
节流在间隔一段时间执行一次回调的场景有:
1,滚动加载,加载更多或滚到底部监听
1,搜索框,搜索联想功能
21,什么是重绘和回流
答: 当影响DOM元素可见性的属性发生变化时,就会重新计算属性,浏览器会重新描绘相应的元素,这个过程叫重绘。
当渲染树中的一部分或者全部因为元素的尺寸、布局、隐藏等改变而需要重新构建的时候,这时候就会发生回流。
触发条件:
1,添加或删除可见的DOM元素
2,元素的位置发生变化
3,元素的尺寸发生变化(包括外边距,内边距,边框大小,高度和宽度等)
4,内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代
5,页面一开始渲染的时候 (这肯定避免不了)
6,浏览器的窗口尺寸变化 (因为回流是根据视口的大小来计算元素的位置和大小的)
7,回流一定会触发重绘,而重绘不一定会回流
如何减少重绘、回流?
1,修改html元素中对应的class名,利用class替换样式
2,csstext(利用cssText 属性合并所有改变,然后一次性写入)
3,避免设置多层内联样式
4,避免使用table布局
5,使用css3硬件加速,可以让transform、opacity、filters等动画不会引起重绘
6,display: none (隐藏元素、应用修改、重新显示)
22,css优先级
答:!import > 内联样式 > 内部样式 > 外部样式
23,如何解决盒子塌陷问题
答:1,为外部盒子添加after伪类,设置clear属性清除浮动(主流)
2,父盒子里最下方引入清除浮动块 (引入了不必要的冗余元素 。)
3,给父盒子添加overflow:auto;或者overflow:hidden;。(当子元素有定位属性时overflow:auto;有可能出现滚动条,影响美观。overflow:hidden;可能会带来内容不可见的问题。)
4,给外部的父盒子也添加浮动,让其也脱离标准文档流。(对页面的布局不是很友好,不易维护。)
5,将盒子大小写死,给每个盒子设定固定的width和height,直到合适为止。(非自适应,浏览器的窗口大小直接影响用户体验。)
24,数组去重
答:1,借助ES6提供的Set结构 new Set()
2,利用 filter() 去重
3,利用for 循环 搭配 indexOf 去重
4,将数组的每一个元素依次与其他元素做比较,发现重复元素,删除
5,借助新数组 通过 indexOf 方法判断当前元素在数组中的索引,如果与循环的下标相等则添加到新数组中
6,利用includes实现数组去重
25,内存泄漏原因
答: 1,接口数据量巨大,前端渲染时占用大量内存。(限制接口的返回数据,或者前端显示分批分页展示数据。)
2,v-if 频繁增删DOM节点,若变量未置为null,则其内部的dom元素则不会释放;
3,代码中存在死循环或递归调用;
4,echarts图未彻底删除;
5,定时器未清除;
6,侦听器未清除;
7,绑在EventBus的事件没有解绑;
8,使用了keep-alive(涉及到actived和deactivated钩子函数。组件移除时需要清理或改变数据,使用deactivated钩子函数)
解决方案:
1,在mounted/created 钩子中绑定了DOM/BOM 对象中的事件,需要清理dom上绑定的事件监听,同时将引用的dom设置为null;
2,执行结束后清理定时器 或者 非必要不用定时器,可以使用nextTick代替;
3,使用了事件监听$ on,需要在beforeDestroy 中做对应解绑($ off)处理
4,变量先申明后使用,闭包执行完成后,将引用的局部变量赋值为null;
5,使用了第三方库初始化,需要在beforeDestroy 中做对应解绑处理;eg: this.map.remove()
6,尽量使用原型对象去定义函数,
26,第一次创建界面触发哪些钩子函数
答:beforeCreate created beforeMount mounted
27,Vuex 五个核心
答:Vuex的5个核心属性分别是 State、 Getter、Mutation 、Action、Module。
1,state:state 为单一状态树,在 state 中需要定义我们所需要管理的数组、对象、字符串等等,只有在这里定义了,在 Vue.js 的组件中才能获取你定义的这个对象的状态。
2,gettergetter 有点类似 Vue.js 的计算属性,当我们需要从 store 的 state中派生出一些状态,那么我们就需要使用 getter,getter 会接收 state 作为第一个参数,而且 getter 的返回值会根据它的依赖被缓存起来,只有 getter 中的依赖值(state 中的某个需要派生状态的值)发生改变的时候才会被重新计算。
3,更改 store 中 state 状态的唯一方法就是提交 mutation,就很类似事件。每个 mutation 都有一个字符串类型的事件类型和一个回调函数,我们需要改变 state 的值就要在回调函数中改变。我们要执行这个回调函数,那么我们需要执行一个相应的调用方法:store.commit。
4,action 可以提交 mutation,在 action 中可以执行 store.commit,而且 action 中可以有任何的异步操作。在页面中如果我们要嗲用这个 action,则需要执行 store.dispatch。
5,module 其实只是解决了当 state 中很复杂臃肿的时候,module 可以将 store 分割成模块,每个模块中拥有自己的 state、mutation、action和 getter。
28,跨域出现原因及解决方案
答:因为浏览器的同源策略的限制问题(协议、主机、端口一致),浏览器访问非同源的网址时,会出现无法获取数据(已发请求,服务器已收到请求),出现跨域问题
解决:1,借助vue-cli脚手架开启代理服务器,在vue.config.js文件中配置proxy,原理:先请求本地服务器,本地服务器再去请求真正的后台服务器,最后本地服务器再将请求回来的数据返回给浏览器(本地服务器跟浏览器之间不存在跨域)
2,后台帮忙解决
29,三种存储方式
答: 1,cookie:数据存储,跨页面通讯,数据每次都会发送给服务端。
2,localStorage:存储数据,跨页面通讯,不会与服务器端通讯,相对与cookie较安全,不用担心数据被截获,只能有前端操作,后端操作不了,存储的时效性是永久的,但是可以手动删除;
3,sessionStorage:存储数据,不会与服务器端通讯,相对与cookie较安全,不用担心数据被截获,只能有前端操作,后端操作不了,仅在当前会话下有效。只要这个浏览器窗口关闭后就会被销毁;
30,dom如何实现浏览器内多个标签⻚之间的通信
答: 1,websocket
2,ShareWorker
3,postMessage
4,localStorage
31,$route和$router的区别
答:$router是用来操作路由,$route是用来获取路由信息
32,虚拟DOM实现原理,为什么要使用虚拟DOM
答: 1,用 JavaScript 对象模拟真实 DOM 树,对真实 DOM 进行抽象;
2,diff 算法 — 比较两棵虚拟 DOM 树的差异;
3,pach 算法 — 将两个虚拟 DOM 对象的差异应用到真正的 DOM 树。
使用原因:直接操作DOM引发页面重排重绘,频繁操作会造成频繁渲染,非常消耗性能;我们希望的是每次修改能够只修改我们想要修改的DOM而不是重新渲染所有的DOM
33,普通函数和箭头函数区别
答: 1、外形不同:箭头函数使用箭头定义,普通函数中没有。
2、 箭头函数全都是匿名函数:普通函数可以有匿名函数,也可以有具名函数
3、箭头函数不能用于构造函数:普通函数可以用于构造函数,以此创建对象实例。
4、箭头函数中 this 的指向不同:在普通函数中,this 总是指向调用它的对象,如果用作构造函数,它指向创建的对象实例。
5、箭头函数不具有 arguments 对象:每一个普通函数调用后都具有一个arguments 对象,用来存储实际传递的参数。但是箭头函数并没有此对象。
6、其他区别:箭头函数不具有 prototype 原型对象。箭头函数不具有 super。箭头函数不具有 new.target
34,怎样理解Vue的单向数据流
答:Vue 的单向数据流:指数据一般从父组件传到子组件,子组件没有权利直接修改父组件传来的数据,即子组件从 props 中直接获取的数据,只能请求父组件修改数据再传给子组件。父级属性值的更新会下行流动到子组件中。
35,slot插槽
答:是组件的一块HTML模板,这块模板由使用组件者即父组件提供。可以说是子组件暴露的一个让父组件传入自定义内容的接口。
slot的作用?:让用户可以拓展组件,去更好地复用组件和对其做定制处理,举一些例子,比如布局组件、表格列、下拉选项
slot怎么用?:slot的用法可以分为三类,分别是默认插槽、具名插槽、作用域插槽
36,keep-alive
答: keep-alive是vue的内置组件,是用来包裹动态组件的,它会缓存不活跃的组件,keep-alive是一个比较抽象的组件,它自己不会渲染dom节点,也不会出现在父组件链中。在组件切换过程中 把切换出去的组件保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性。