前端常见面试题
Posted qq_42802170
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端常见面试题相关的知识,希望对你有一定的参考价值。
文章目录
- HTML+CSS部分
- javascript部分
- 1.请描述一下cookies、sessionStorage和localStorage的区别
- 2.一次完整的HTTP事务是怎样的一个过程
- 3.javascript的原型,原型链是什么,有什么特点?
- 4.继承有哪些方式?
- 1.原型链继承 (很少用)
- 2.借用构造函数(伪造对象)(很少用)
- 3.组合继承(常用的继承方式)
- 4.经典继承(规范化的原生式继承)
- 5.寄生组合式继承
- 5.前端性能优化?(例举至少5项)
- 6.什么是闭包?有什么作用?优缺点?使用场景?
- 7.递归
- 8.常见兼容性问题?
- 移动端兼容问题
- 9.前端常见的跨域解决方案?
- 10.this指向
- 11.Ajax的实现步骤
- 12.call apply bind的区别
- 13.浅拷贝和深拷贝
- 14.new关键字作用
- 15.对ES6中Promise的理解?
- 16.请写出至少 5 种常见的 http 状态码以及代表的意义
- 17.get和post的区别?
- 18.从URL地址中获取参数值的方法
- 19、浏览器的渲染机制
- 20、js的执行机制
- 宏任务和微任务
- 21、Vue-router跳转和location.href有什么区别?
- 22、数组去重的方法
- 23、es6中项目中使用到的点
- 24、箭头函数和普通函数的区别
- 25、重绘和重排的区别?
- 26、如何减少http请求
- 27、如果使用闭包如何减少内存泄漏
- 28、import 和require的区别
- 29、防抖和节流(作用:降频)
- 30、TCP三次握手和四次挥手
- vue部分
- 1.简述Vue的响应式原理?
- 2.vue路由的跳转传参与参数获取,各两种方式
- 3.vue的生命周期是什么?并详细说下你对vue生命周期的理解?
- 4. 第一次页面加载会触发哪几个钩子?
- 5.vue组件之间的通讯方式有哪些?
- 6.vue-router有哪几种导航钩子
- 7.keep-alive的作用是什么?
- 8.vuex有哪几种属性?并描述一下各个属性的作用
- **9.分别简述computed和watch的使用场景**
- 10.computed和watch的区别?
- 11.$nextTick的使用
- 12.vue组件中data为什么必须是一个函数?
- 13.created和mounted的区别
- 14.$route 和 $router 的区别
- 15.单页面应用优缺点?
- 16、scoped的原理
- 17、Vue动态菜单(路由)的实现方案
- 18、权限分配实现
- 19、权限管理做法?
- 20、路由懒加载实现
- 21、hash和history模式的区别
- 22、 说一下vue开发环境和线上环境如何切换?
- 23、token过期问题处理
- 24、vue2与vue3的区别
- webpack部分
- 其它:
html+CSS部分
1.如何使一个元素在水平和垂直方向上居中?
方法一: 采用弹性盒子
display: flex;
align-items: center;
justify-content: center;
方法二: 定位+位移
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
方法三: 给子盒子设置定位的上下左右都为0 ,,然后设置margin自动适应
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
方法四: 定位+子盒子左边距、上边距的一半
width: 100px;
height: 100px;
background-color: blue;
position: absolute;
left: 50%;
top: 50%;
margin-left: -50px;//为宽度的一半
margin-top: -50px;//为高度的一半
2.如何清除浮动?
方法一:父级添加overflow属性方法
可以给父级添加: overflow为 hidden| auto| scroll 都可以实现。
方法二: 使用after伪元素清除浮动
.clearfix:after { content: ""; display: block; height: 0; clear: both; visibility: hidden; }
.clearfix {*zoom: 1;} /* IE6、7 专有 */
方法三: 使用双伪元素清除浮动
.clearfix:before,.clearfix:after {
content:"";
display:table;
}
.clearfix:after {
clear:both;
}
.clearfix {
*zoom:1;
}
3.css优先级算法如何计算?
选择器 | 计算权重公式 |
---|---|
继承或者* | 0,0,0,0 |
标签选择器 | 0,0,0,1 |
每个类,伪类 | 0,0,1,0 |
每个ID | 0,1,0,0 |
每个行内样式 | 1,0,0,0 |
每个!important | 无穷大 |
4.html5有哪些新特性?
1.拖拽释放(Draganddrop)API ondrop 自定义属性 data-id 获取 li.getAttribute(‘data-id’)或者 li.dataset.type=‘guoji’
2.语义化更好的内容标签(header,nav,footer,aside,article,section)
3.音频、视频 API(audio,video) 如果浏览器不支持自动播放怎么办?
4.画布(Canvas)API 热 canvas 和 image 的区别?
5.地理(Geolocation)API
6.本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失;sessionStorage 的数据在浏览器关闭后自动删除
7.表单控件,calendar、date、time、email、url、search 、tel、file、number
9.新的技术 webworker,websocket,Geolocation
5.CSS选择符有哪些?哪些属性可以继承?优先级算法如何计算?CSS3新增伪类有哪些?
CSS 选择符:
1.id选择器(# myid)
2.类选择器(.myclassname)
3.标签选择器(div, h1, p)
4.相邻选择器(h1 + p)
5.子选择器(ul > li)
6.后代选择器(li a)
7.通配符选择器( * )
8.属性选择器(a[rel = “external”])
9.伪类选择器(a: hover, li:nth-child)
可继承的样式:
1.font-size
2.font-family
3.color
4.text-indent
不可继承的样式:
1.border
2.padding
3.margin
4.width
5.height
优先级算法:
1.优先级就近原则,同权重情况下样式定义最近者为准;
2.载入样式以最后载入的定位为准;
3.!important > id > class > tag
4.important 比 内联优先级高,但内联比 id 要高
CSS3新增伪类举例:
p:first-of-type 选择属于其父元素的首个
元素的每个
元素。
p:last-of-type 选择属于其父元素的最后
元素的每个
元素。
p:only-of-type 选择属于其父元素唯一的
元素的每个
元素。
p:only-child 选择属于其父元素的唯一子元素的每个
元素。
p:nth-child(2) 选择属于其父元素的第二个子元素的每个
元素。
:enabled :disabled 控制表单控件的禁用状态。
:checked 单选框或复选框被选中。
6.CSS3新特性
1.过渡 transition: CSS属性,花费时间,效果曲线(默认ease),延迟时间(默认0)复制代码
2.动画 animation:动画名称,一个周期花费时间,运动曲线(默认ease),动画延迟(默认0),播放次数(默认1),是否反向播放动画(默认normal),是否暂停动画(默认running)复制代码
3.形状转换 transform:适用于2D或3D转换的元素
rotate(30deg); translate(30px,30px); scale(.8); skew(10deg,10deg); rotateX(180deg); rotateY(180deg); rotate3d(10,10,10,90deg);
4.选择器
5.阴影 box-shadow: 水平阴影的位置 垂直阴影的位置 模糊距离 阴影的大小 阴影的颜色 阴影开始方向(默认是从里往外,设置inset就是从外往里);复制代码
6.边框 border-image: 图片url 图像边界向内偏移 图像边界的宽度(默认为边框的宽度) 用于指定在边框外部绘制偏移的量(默认0) 铺满方式–重复(repeat)、拉伸(stretch)或铺满(round)(默认:拉伸(stretch));
7.背景 background-clip 制定背景绘制(显示)区域 background-origin background-size
1.(background-clip: border-box;)默认情况(从边框开始绘制) 2.(background-clip: padding-box;)从padding开始绘制(显示),不算border,,相当于把border那里的背景给裁剪掉! 3.(background-clip: content-box;)只在内容区绘制(显示),不算padding和border,相当于把padding和border那里的背景给裁剪掉!
8.文字 换行 语法:word-break: normal|break-all|keep-all;、语法:word-wrap: normal|break-word; 超出省略号 text-overflow:clip|ellipsis|string
文字阴影 语法:text-shadow:水平阴影,垂直阴影,模糊的距离,以及阴影的颜色。
9.颜色 rgba(rgb为颜色值,a为透明度)
10.渐变
11.弹性布局 Flex
12.盒模型定义 box-sizing:border-box的时候,边框和padding包含在元素的宽高之内!
box-sizing:content-box的时候,边框和padding不包含在元素的宽高之内!
13.媒体查询
7、什么是BFC哪些情况会产生BFC?
1)定义: BFC(Block formatting context)直译为"块级格式化上下文"。它是一个独立的渲染区域,只有 Block-level box 参与, 它规定了内部的 Block-level Box 如何布局,并且与这个区域外部毫不相干。
2)布局规则:
A. 内部的 Box 会在垂直方向,一个接一个地放置。
B. Box 垂直方向的距离由 margin 决定。属于同一个 BFC 的两个相邻 Box 的 margin 会发生重叠。
C. 每个元素的 margin box 的左边, 与包含块 border box 的左边相接触(对于从左往右的格式化, 否则相反)。即使存在浮动也是如此。
D. BFC 的区域不会与 float box 重叠。
E. BFC 就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也 如此。
F. 计算 BFC 的高度时,浮动元素也参与计算。
3)哪些元素会生成 BFC:
A. 根元素
B. float 属性不为 none
C. position 为 absolute 或 fixed
D. display 为 inline-block, table-cell, table-caption, flex, inline-flex
F. overflow 不为 visible
javascript部分
1.请描述一下cookies、sessionStorage和localStorage的区别
不同点:
(1)存储大小
cookie数据大小不能超过4k。
sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
(2)有效时间
localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;
sessionStorage 数据在当前浏览器窗口关闭后自动删除
cookie 设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭
(3) 数据与服务器之间的交互方式
cookie的数据会自动的传递到服务器,服务器端也可以写cookie到客户端 , 每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题
sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存
2.一次完整的HTTP事务是怎样的一个过程
域名解析 --> 发起TCP的3次握手 --> 建立TCP连接后发起http请求 --> 服务器响应http请求,浏览器得到html代码 --> 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等) --> 浏览器对页面进行渲染呈现给用户
3.javascript的原型,原型链是什么,有什么特点?
原型是一个对象,我们称prototype为原型对象。
原型的作用就是共享方法
每一个实例对象有一个proto属性,指向的构造函数的原型对象,构造函数的原型 对象也是一个对象,也有proto属性,这样一层一层往上找就形成了原型链。
4.继承有哪些方式?
1.原型链继承 (很少用)
原理:让子类构造函数的原型指向父类型构造函数的一个实例
2.借用构造函数(伪造对象)(很少用)
原理:在子类型构造函数中执行父类构造函数,并将父类构造函数的this指向子类的new出来的对象上
解决问题:父类有引用类型对象的属性时,继承后实例间也不会相互影响
存在问题:1、父类中相同的方法也需要创建多次,浪费内存 2、子类访问不到父类原型的属性和方法了。
3.组合继承(常用的继承方式)
(组合原型链继承和借用构造两种方式)
这种方式解决了原型链继承和借用构造函数继承两种方式带来的问题,融合了两种方式的优点,目前最常用的方式
存在一个小问题,此时子类的constructor不再是自身构造函数了
4.经典继承(规范化的原生式继承)
原理:利用Object.create()
优点:不需要兴师动众使用构造函数
存在问题:对象中有引用类型值属性时,实例间会相互影响
5.寄生组合式继承
原理:在组合继承的前提下,子类原型指向父类原型的一个副本而不是父类的实例
优化了组合继承(子类.construtor指向问题)的小问题,是最理想的继承了
5.前端性能优化?(例举至少5项)
1. 尽可能的减少 HTTP 的请求数 | content |
---|---|
2. 使用 CDN(Content Delivery Network) | server |
3. 添加 Expires 头(或者 Cache-control ) | server |
4. Gzip 组件 | server |
5. 将 CSS 样式放在页面的上方 | css |
6. 将脚本移动到底部(包括内联的) | javascript |
7. 避免使用 CSS 中的 Expressions | css |
8. 将 JavaScript 和 CSS 独立成外部文件 | javascript css |
9. 减少 DNS 查询 | content |
10. 压缩 JavaScript 和 CSS (包括内联的) | javascript css |
11. 避免重定向 | server |
12. 移除重复的脚本 | javascript |
13. 配置实体标签(ETags) | css |
14. 使 AJAX 缓存 |
1. 加载优化
-
压缩合并
-
代码分割(code spliting),可以基于路由或动态加载
-
第三方模块放在CDN
-
大模块异步加载,例如: Echarts,可以使用require.ensure,在加载成功后,在显示对应图表
-
小模块适度合并,将一些零散的小模块合并一起加载,速度较快
-
可以使用pefetch预加载,在分步场景中非常适合
2. 图片优化
-
小图使用雪碧图,iconFont,base64内联
-
图片使用懒加载
-
webp代替其他格式
-
图片一定要压缩
-
可以使用的img的srcset,根据不同分辨率显示不同尺寸图片,这样既保证显示效果,又能节省带宽,提高加载速度
3.css优化
-
css写在头部
-
避免css表达式
-
移除空置的css规则
-
避免行内style样式
4、js优化
-
js写在body底部
-
js用defer放在头部,提前加载时间,又不阻塞dom解析
-
script标签添加crossorigin,方便错误收集
5. 渲染优化
- 尽量减少reflow和repaint
涉及到样式,尺寸,节点增减的操作,都会触发reflow和repaint。
1.1 用变量缓存dom样式,不要频繁读取
1.2 通过DocumentFragment或innerHTML批量操作dom
1.3 dom隐藏,或复制到内存中,类似virtual dom,进行修改,完成后再替换回去
6. 首屏优化
原则:显示快,滚动流畅,懒加载,懒执行,渐进展现
-
代码分离,将首屏不需要的代码分离出去
-
服务端渲染或预渲染,加载完html直接渲染,减少白屏时间
-
DNS prefetch,使用dns-prefetch减少dns查询时间,PC端域名发散,移动端域名收敛
-
减少关键路径css,可以将关键的css内联,这样可以减少加载和渲染时间
7. 打包优化(主要是webpack优化)
-
拆包 externals dllPlugin
-
提取公共包 commonChunkPlugin或splitChunks
-
缩小范围 各种loader配置include和exclude,noParse跳过文件
-
开启缓存 各种loader开启cache
-
多线程加速 happypack或thead-loader
-
tree-shaking ES模块分析,移除死代码
8. vue****优化
-
路由懒加载组件
-
keep-alive缓存组件,保持原显示状态
-
列表项添加key,保证唯一, 避免数据混乱 , 用来提高渲染性能
-
列表项绑定事件,使用事件代理(v-for)
-
v-if和v-for不要用在一个标签上,它会在每个项上进行v-if判断
10. SEO****优化
-
添加各种meta信息
-
预渲染
-
服务端渲染
6.什么是闭包?有什么作用?优缺点?使用场景?
闭包(closure)指有权访问另一个函数作用域中变量的函数。
闭包最大用处有两个:
1.可以读取函数内部的变量。
2.让变量的值始终保持在内存中,不会在被外部函数调用后自动删除。
总结:局部变量无法共享和长久保存,而全局变量可能造成变量污染,当我们希望有一种机制即可以长久保存变量又不会造成全局污染。
案例:
<div class="nav">
<li>苹果</li>
<li>香蕉</li>
<li>梨子</li>
<li>菠萝</li>
</div>
<script>
var lis = document.querySelector('.nav').querySelectorAll('li');
for (var i = 0; i < lis.length; i++) {
(function (i) {
lis[i].onclick = function () {
console.log(i);
}
})(i)
}
</script>
优点:延伸了变量的作用范围
缺点:占用内存过多
7.递归
一个函数在内部可以调用本身,这个函数就是递归函数
递归函数的作用和循环效果一样
由于递归函数很容易发生“栈溢出”,所以要加退出条件return
案例
var num = 1;
function fn() {
console.log("打印6句话");
if (num == 6) {
return
}
num++;
fn()
}
fn()
8.常见兼容性问题?
(1)浏览器兼容问题一:不同浏览器的标签默认的外补丁和内补丁不同 问题症状:随便写几个标签,不加样式控制的情况下,各自的margin 和padding差异较大。 碰到频率:100% 解决方案:CSS里 {margin:0;padding:0;} 备注:这个是最常见的也是最易解决的一个浏览器兼容性问题,几乎所有的CSS文件开头都会用通配符来设置各个标签的内外补丁是0。
(2)浏览器兼容问题二:块属性标签float后,又有横行的margin情况下,在IE6显示margin比设置的大 问题症状:常见症状是IE6中后面的一块被顶到下一行 碰到频率:90%(稍微复杂点的页面都会碰到,float布局最常见的浏览器兼容问题) 解决方案:在float的标签样式控制中加入 display:inline;将其转化为行内属性 备注:我们最常用的就是div+CSS布局了,而div就是一个典型的块属性标签,横向布局的时候我们通常都是用div float实现的,横向的间距设置如果用margin实现,这就是一个必然会碰到的兼容性问题。
(3)浏览器兼容问题三:设置较小高度标签(一般小于10px),在IE6,IE7,遨游中高度超出自己设置高度 问题症状:IE6、7和遨游里这个标签的高度不受控制,超出自己设置的高度 碰到频率:60% 解决方案:给超出高度的标签设置overflow:hidden;或者设置行高line-height 小于你设置的高度。 备注:这种情况一般出现在我们设置小圆角背景的标签里。出现这个问题的原因是IE8之前的浏览器都会给标签一个最小默认的行高的高度。即使你的标签是空的,这个标签的高度还是会达到默认的行高。
(4)浏览器兼容问题四:行内属性标签,设置display:block后采用float布局,又有横行的margin的情况,IE6间距bug 问题症状:IE6里的间距比超过设置的间距 碰到几率:20% 解决方案 : 在display:block;后面加入display:inline;display:table; 备注:行内属性标签,为了设置宽高,我们需要设置display:block;(除了input标签比较特殊)。在用float布局并有横向的margin后,在IE6下,他就具有了块属性float后的横向margin的bug。不过因为它本身就是行内属性标签,所以我们再加上display:inline的话,它的高宽就不可设了。这时候我们还需要在display:inline后面加入display:talbe。
(5) 浏览器兼容问题五:图片默认有间距 问题症状:几个img标签放在一起的时候,有些浏览器会有默认的间距,加了问题一中提到的通配符也不起作用。 碰到几率:20% 解决方案:使用float属性为img布局 备注 : 因为img标签是行内属性标签,所以只要不超出容器宽度,img标签都会排在一行里,但是部分浏览器的img标签之间会有个间距。去掉这个间距使用float是正道。(使用负margin,虽然能解决,但负margin本身就是容易引起浏览器兼容问题的用法,所以我禁止他们使用)
(6) 浏览器兼容问题六:标签最低高度设置min-height不兼容 问题症状:因为min-height本身就是一个不兼容的CSS属性,所以设置min-height时不能很好的被各个浏览器兼容 碰到几率:5% 解决方案:如果我们要设置一个标签的最小高度200px,需要进行的设置为:{min-height:200px; height:auto !important; height:200px; overflow:visible;} 备注:在B/S系统前端开时,有很多情况下我们又这种需求。当内容小于一个值(如300px)时。容器的高度为300px;当内容高度大于这个值时,容器高度被撑高,而不是出现滚动条。这时候我们就会面临这个兼容性问题。
(7)浏览器兼容问题七:透明度的兼容CSS设置 一般在ie中用的是filter:alpha(opacity=0);这个属性来设置div或者是块级元素的透明度,而在firefox中,一般就是直接使用opacity:0,对于兼容的,一般的做法就是在书写css样式的将2个都写上就行,就能实现兼容
移动端兼容问题
一、在移动端使用click事件有300ms延迟的问题
- 禁止双击缩放===》meta:user-scalabel=no
- fastclick.js
二、在移动端中,如果给元素设置一个1px的像素边框的话,那么在手机上看起来是会比一个像素粗的
解决方法:使用伪类元素模拟边框使用transform缩放。
三、input 的placeholder会出现文本位置偏上的情况
input 的placeholder会出现文本位置偏上的情况:PC端设置line-height等于height能够对齐,而移动端仍然是偏上,解决是设置line-height:normal
9.前端常见的跨域解决方案?
-
通过jsonp
通常为了减轻web服务器的负载,我们把js、css,img等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,而被浏览器允许,基于此原理,我们可以通过动态创建script,再请求一个带参网址实现跨域通信。
jsonp缺点:只能实现get一种请求。
-
location.hash + iframe跨域
实现原理: a欲与b跨域相互通信,通过中间页c来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。
-
跨域资源共享(CORS)
普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置
-
nginx反向代理接口跨域
实现思路:通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录
-
WebSocket协议跨域
WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是server push技术的一种很好的实现
10.this指向
调用方式 | this指向 |
---|---|
普通函数调用 | window |
构造函数调用 | 实例对象,原型对象里面的方法也指向实例对象 |
对象方法调用 | 该方法所属对象 |
事件绑定方法 | 绑定事件对象 |
定时器函数 | window |
立即执行函数 | window |
11.Ajax的实现步骤
1.创建ajax对象
var xhr = new XMLHttpRequest();
2.告诉 Ajax 请求地址以及请求方式
xhr.open('get', 'http://www.example.com');
3.发送请求
xhr.send();
4.获取服务器端给与客户端的响应数据
xhr.onload = function () {
console.log(xhr.responseText);
}
12.call apply bind的区别
相同点:
都可以改变this指向
区别点:
1.call和apply会调用函数,并且改变函数内部this指向
2.call和apply传递的参数不一样,call传递参数aru1,aru2…形式,apply必须是数组形式[arg];
3.bind不会调用函数,可以改变函数内部this指向
主要应用场景
1.call经常做继承
2.apply经常跟数组有关系,比如借助数学对象实现数组的最大值和最小值
3.bind不调用函数,但是可以改变this指向,比如改变定时器内部的this指向
13.浅拷贝和深拷贝
简单表述:假设B复制了A,当A修改时,看B是否发生变化,如果B也跟着变化,说明这个是浅拷贝,如果B没变那就是深拷贝
1、浅拷贝方实现方式(改变地址值)
- (遍历赋值,for…in)
- (Object.assign())
2、深拷贝方实现方式
- (遍历赋值,for…in)
- (JSON.parse和JSON.stringify)
14.new关键字作用
- 在内存中创建一个新的空对象。
- 让this指向创建出来的空对象。
- 执行构造函数里面的代码,给这个空的对象添加属性和方法。
- 返回这个新对象(所以构造函数里面不需要return)。
15.对ES6中Promise的理解?
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。所谓 Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是 一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。 Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
特点:
1、自己身上有 all、reject、resolve 这几个方法
2、原型上有 then、catch,finally 等方法
3、一旦建立,就无法取消,这是它的缺点
16.请写出至少 5 种常见的 http 状态码以及代表的意义
5 种常见的 http 状态码以及代表的意义如下:
200(OK) :请求已成功,请求所希望的响应头或数据体将随此响应返回。
303(SeeOther) :告知客户端使用另一个 URL 来获取资源。
304( Not Modified ): 未修改, 服务端已经执行了GET,但文件未变化
400(Bad Request) :请求格式错误。1)语义有误,当前请求无法被服务器 理解。除非进行修改,否则客户端不应该重复提交这个请求;2)请求参数有误。
401 :未授权
403( Forbidden ): 服务器理解请求客户端的请求,但是拒绝执行此请求
404(NotFound) :请求失败,请求所希望得到的资源未被在服务器上发现。
500(InternalServerError) :服务器遇到了一个未曾预料的状况,导致了它 无法完成对请求的处理
17.get和post的区别?
1.GET请求会被缓存,而POST请求不会被缓存
2.GET请求会被保留在浏览器历史中,而POST请求则不会
3.GET的安全性相对于POST较差,因为发送的数据是URL的一部分,而POST不会放到浏览器历史中
4.GET向URL中传递数据,对数据长度有限制,POST则没有限制
18.从URL地址中获取参数值的方法
原理:主要利用split()将字符串转换成数组,然后存放到数组里,最后把key和value存放到一个新的对象里,通过名字就可获取对象里的值。
示例:
var url = 'https://gitbook.cn/gitchat/geekbooks?tag=JavaScript&name=pwwu&age=24';
var temp1 = url.split('?');
var pram = temp1[1];
var keyValue = pram.split('&');
var obj = {};
for (var i = 0; i<keyValue.length; i++){
var item = keyValue[i].split('=');
var key = item[0];
var value = item[1];
obj[key] = value;
}
console.log(obj); // {tag:'JavaScript',name:'pwwu',age:'24'}
19、浏览器的渲染机制
-
DOM树构建
-
CSSOM树构建
css加载不会阻塞DOM树解析,但会阻塞render树渲染
-
RenderObject树构建
-
布局
-
绘制
20、js的执行机制
1.先执行执行栈中的同步任务
2.异步任务(回调函数)放入通过异步进程处理判断能不能放入任务队列中
3.一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行
由于主线程不断地从任务队列中重复获得任务,执行任务,在获取任务,再执行这种机制被称为事件循环(event loop)
宏任务和微任务
宏任务:
setTimeout
setInterval
setImmediate
requestAnimationFrame
微任务:
process.nextTick
MutationObserver
Promise.then catch finally
21、Vue-router跳转和location.href有什么区别?
使用location.href=’/url’来跳转,简单方便,但是刷新了页面;
使用router.push(’/url’)来跳转,使用了diff算法,实现了按需加载,减少了dom的消耗。
22、数组去重的方法
方法一:利用展开运算符和Set成员的唯一性(ES6)
let arr = [1, 2, 3, 4, 4, 3, 2, 1];
function unique(arr) {
return [...new Set(arr)];
}
console.log(unique(arr)) // [1, 2, 3, 4]
方法二:利用indexOf
var arr = [1, 2, 3, 4, 4, 3, 2, 1];
function unique(arr) {
var res = [];
for (var i = 0; i < arr.length; i++) {
if (res.indexOf(arr[i]) === -1) {
res.push(arr[i])
}
}
return res;
}
console.log(unique(arr)); // [1, 2, 3, 4]
23、es6中项目中使用到的点
1.变量声明的方式:let const
2.模板字符串:反引号``
3.函数里面:箭头函数,传参的时候使用默认参数,
4.解构,剩余参数的使用
5.展开运算符
6.class
7.promise
8.export/import
24、箭头函数和普通函数的区别
- 箭头函数不能用于构造函数,不能使用new
- 箭头函数中this的指向不同 , 在普通函数中,this总是指向调用它的对象 ,箭头函数没有自身的this.一般是指向父级作用域
- .箭头函数不绑定arguments,取而代之用rest参数…解决
25、重绘和重排的区别?
重绘不一定需要重排,重排必然会导致重绘
1、重排:当渲染树的一部分必须更新并且节点的尺寸发生了变化,浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树。
1)添加、删除可见的dom
2)元素的位置改变
3)元素的尺寸改变(外边距、内边距、边框厚度、宽高等几何属性)
4)页面渲染初始化
5)浏览器窗口尺寸改变
2、重绘:是在一个元素的外观被改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。
26、如何减少http请求
1、使用雪碧图
2、使用keep-alive保留组件状态或避免重新渲染
3、gzip压缩资源
27、如果使用闭包如何减少内存泄漏
- 在退出函数之前,将不使用的局部变量全部删除。可以使变量赋值为null;
- 避免变量的循环赋值和引用
28、import 和require的区别
区别1:模块加载的时间
require:运行时加载
import:编译时加载(效率更高)【由于是编译时加载,所以import命令会提升到整个模块的头部】
区别2:模块的本质
require : CommonJs模块
import :ES6模块
区别3:严格模式
CommonJs模块和ES6模块的区别
(1)CommonJs模块默认采用非严格模式
(2)ES6 的模块自动采用严格模式,不管你有没有在模块头部加上 “use strict”;
(3)CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用
29、防抖和节流(作用:降频)
防抖:debounce 以10秒为例。如果在10s之内重复调用函数,则再次延迟10秒执行,如果10s不去执行它,则顺序执行这个函数。如坐电梯
节流:throttle 以10秒为例。两次执行之间,至少间隔10秒,否则不与执行。如水龙头
前端其它的场景需做降频:窗口缩放、鼠标移动,input、scroll
30、TCP三次握手和四次挥手
三次握手
第一次握手:
客户端向服务端发起请求,已确认服务端是否能够收到请求
第二次握手
服务端响应客户端,告诉它我收到你的请求,并且准备接收其它请求了
第三次握手
客户端再次向服务端再次发起请求,告诉服务端我也收到了你的回复,我也准备好了
四次挥手是客户端与服务端结束通讯的时候
第一次挥手
客户端向服务端发起结束请求
第二次挥手
服务端响应客户端表示我收到你的结束请求的通知了
第三次挥手
仍然是服务端向客户端发起,因为服务端在收到这样的结束通知之后去处理现有的数据请求了,在现有的数据处理完成之后,会正式回复客户端的结束请求
第四次挥手
客户端向服务端发起表示收到了你的结束回复
vue部分
1.简述Vue的响应式原理?
回答一:
这里的响应式指的是,当你的数据有变化,vue能够做出响应,然后去重新渲染页面,它采用数据劫持结合发布者—订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter getter,在数据变动时发布消息给订阅者,触发响应的监听回调。
回答二:
1.data的属性被转化为getter和setter,并且记录相应的依赖,当它被改动的时候会通知相应的依赖
2.所有的组件实例会有它对应的watcher实例,而watcher实例会依赖于相应的setter
3.当数据变化时,setter会被调用,setter会通知对应的watcher,watcher会更新相应的视图
2.vue路由的跳转传参与参数获取,各两种方式
一、动态路由
- 定义 {path:’/地址:id’}
- 调用传递
- this.$router.push(’/地址/123’)
- this.$router.push({name:’’,params:{id:123}})
- 获取参数 this.$route.params.id
二、地址传参
- 定义 {path:’/地址’}
- 调用传递
- this.$router.push(’/地址?a=1 & b=2’)
- this.$router.push({path:’/地址’,query:{a:1,b:2}})
- 获取参数 this.$route.query.a
二者区别:
动态路由:在以对象格式传参时,是name+params,并不是所有参数在地址栏中可见
地址传参:在以对象的格式传参时,是path+query,所有参数都会在地址栏中可见
3.vue的生命周期是什么?并详细说下你对vue生命周期的理解?
Vue实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载DOM->渲染、更新->卸载等一系列过程,我们称这是Vue的生命周期。
总共分为 8 个阶段创建前/后,载入前/后,更新前/后,销毁前/后。创建前/后:
1.beforeCreate:在new一个vue实例后,只有一些默认的生命周期钩子和默认事件,其他的东西都还没创建。在beforeCreate生命周期执行的时候,data和methods中的数据都还没有初始化。不能在这个阶段使用data中的数据和methods中的方法
2.created:data 和 methods都已经被初始化好了,如果要调用 methods 中的方法,或者操作 data 中的数据,最早可以在这个阶段中操作
3.beforeMount:执行到这个钩子的时候,在内存中已经编译好了模板了,但是还没有挂载到页面中,此时,页面还是旧的
4.mounted:执行到这个钩子的时候,就表示Vue实例已经初始化完成了。此时组件脱离了创建阶段,进入到了运行阶段。 如果我们想要通过插件操作页面上的DOM节点,最早可以在和这个阶段中进行
5.beforeUpdate: 当执行这个钩子时,页面中的显示的数据还是旧的,data中的数据是更新后的, 页面还没有和最新的数据保持同步
6.updated:页面显示的数据和data中的数据已经保持同步了,都是最新的
7.beforeDestory:Vue实例从运行阶段进入到了销毁阶段,这个时候上所有的 data 和 methods , 指令, 过滤器 ……都是处于可用状态。还没有真正被销毁
8.destroyed: 这个时候上所有的 data 和 methods , 指令, 过滤器 ……都是处于不可用状态。组件已经被销毁了。
4. 第一次页面加载会触发哪几个钩子?
第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子
5.vue组件之间的通讯方式有哪些?
1、父组件向子组件传递数据
- 把要传递给子组件的数据,作为自定义属性通过’v-bind’,绑定到子组件身上
- 子组件通过props接收
2、子组件向父组件传值
- 把要传递给子组件的方法,通过事件绑定’v-on’,绑定到子组件身上
- 子组件通过this.$emit()方法调用传递过来的方法
3、provide 与 inject(依赖注入)
- 在祖先组件定义
provide
属性,返回传递的值 - 在后代组件通过
inject
接收组件传递过来的值
4、vuex
5、多级组件传递数据
A包含B组件,B包含C组件 那么A 传递到C 组件可以通过 在B组件中绑定 $attrs
6.vue-router有哪几种导航钩子
1、全局导航钩子:router.beforeEach(to,from,next),作用:跳转前进行判断拦截。
2、组件内的钩子;
3、单独路由独享组件
7.keep-alive的作用是什么?
包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染
属性及生命周期钩子:
1、activated:页面第一次进入的时候,钩子触发的顺序是created->mounted->activated
2、deactivated :页面退出的时候会触发deactivated,当再次前进或者后退的时候只触发activated
8.vuex有哪几种属性?并描述一下各个属性的作用
有五种,分别是 State、 Getter、Mutation 、Action、 Module
vuex的State特性是?
1、Vuex 就是一个仓库,仓库里面放了很多对象。其中 state 就是数据源存放地,对应于与一般 Vue 对象 里面的 data。
2、state 里面存放的数据是响应式的,Vue 组件从 store 中读取数据,若是 store 中的数据发生改变,依赖 这个数据的组件也会发生更新。
3、它通过 mapState 把全局的 state 和 getters 映射到当前组件的 computed 计算属性中。
vuex的Getter特性是
1、getters 可以对 State 进行计算操作,它就是 Store 的计算属性
2、 虽然在组件内也可以做计算属性,但是 getters 可以在多组件之间复用
3、 如果一个状态只在一个组件内使用,是可以不用 getters
vuex的Mutation特性是?
1、Action 类似于 mutation,不同在于:
2、Action 提交的是 mutation,而不是直接变更状态。
3、Action 可以包含任意异步操作
9.分别简述computed和watch的使用场景
答:computed:
当一个属性受多个属性影响的时候就需要用到computed
最典型的栗子: 购物车商品结算的时候
watch:
当一条数据影响多条数据的时候就需要用watch
栗子:搜索数据
10.computed和watch的区别?
computed:
- 支持缓存,只有依赖数据发生改变,才会重新进行计算
- 不支持异步,当computed内有异步操作时无效,无法监听数据的变化
- computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值
- 适合监听多个数据
- 如果computed属性属性值是函数,那么默认会走get方法;函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。
watch:
-
不支持缓存,数据变,直接会触发相应的操作;
-
.watch支持异步;
-
监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;
-
适合监听单个数据
-
监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作,函数有两个参数,
immediate:组件加载立即触发回调函数执行,
deep: 深度监听,为了发现对象内部值的变化,复杂类型的数据时使用,例如数组中的对象内容的改变,注意监听数组的变动不需要这么做。注意:deep无法监听到数组的变动和对象的新增,参考vue数组变异,只有以响应式的方式触发才会被监听到
11.$nextTick的使用
当你修改了data的值然后马上获取这个dom元素的值,是不能获取到更新后的值,
你需要使用$nextTick这个回调,让修改后的data值渲染更新到dom元素之后在获取,才能成功。
12.vue组件中data为什么必须是一个函数?
组件中的data写成一个函数,数据以函数返回值的形式定义,这样每次复用组件的时候,都会返回一份新的data,相当于每个组件实例都有自己私有的数据空间,它们只负责各自维护的数据,不会造成混乱。而单纯的写成对象形式,就是所有的组件实例共用了一个data,这样改一个全都改了。
13.created和mounted的区别
答:created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
14.$route 和 $router 的区别
r o u t e r 是 V u e R o u t e r 的 实 例 , 在 s c r i p t 标 签 中 想 要 导 航 到 不 同 的 U R L , 使 用 router是VueRouter的实例,在script标签中想要导航到不同的URL,使用 router是VueRouter的实例,在script标签中想要导航到不同的URL,使用router.push方法。返回上一个历史history用$router.to(-1)
$route为当前router跳转对象。里面可以获取当前路由的name,path,query,parmas等。
15.单页面应用优缺点?
优点:
单页应用的内容的改变不需要重新加载整个页面,获取数据也是通过Ajax异步获取,没有页面之间的切换,就不会出现“白屏现象”,也不会出现假死并有“闪烁”现象,页面显示流畅,web应用更具响应性和更令人着迷。
后端不再负责模板渲染、输出页面工作,后端API通用化,即同一套后端程序代码,不用修改就可以用于Web界面、手机、平板等多种客户端。
单页应用相对服务器压力小,服务器只用出数据就可以,不用管展示逻辑和页面合成,吞吐能力会提高几倍。
缺点:
解决方案:
- Vue-router懒加载
Vue-router懒加载就是按需加载组件,只有当路由被访问时才会加载对应的组件,而不是在加载首页的时候就加载,项目越大,对首屏加载的速度提升得越明显。
- 使用CDN加速
在做项目时,我们会用到很多库,采用cdn加载可以加快加载速度。
16、scoped的原理
vue中的scoped属性的效果主要通过PostCSS转译实现 , PostCSS给一个组件中的所有dom添加了一个独一无二的动态属性,然后,给CSS选择器额外添加一个对应的属性选择器来选择该组件中dom,这种做法使得样式只作用于含有该属性的dom——组件内部dom。
17、Vue动态菜单(路由)的实现方案
分以下几步:
1.前端在本地写好路由表,以及每个路由对应的角色,也就是哪些角色可以看到这个菜单/路由;
2.登录的时候,向后端请求得到登录用户的角色(管理者、普通用户);
3.利用路由拦截,根据取到的用户角色,跟本地的路由表进行对比,过滤出用户对应的路由,并利用路由进行左侧菜单渲染
18、权限分配实现
点击分配权限按钮,把当前角色的id放在data中,点击确定按钮时候,先获取到整个树型结构中
半选和全选状态的id值合并到完整的数组中,把得到的数组做了一次字符串的拼接,用英文的逗号隔开
发送请求把保存的角色id和新拼接的id字符串发送到服务器端
19、权限管理做法?
首先做一个用户管理,包括用户的增删改查,还得做一个后台左侧菜单管理,包括增删改查,以及二级菜单的增删改查,系统有一个超级管理员,可以对所有普通用户分配权限,分配完权限之后,这个用户下次登录就可以看到权限之内的菜单,这叫做随意分配权限,还有一种按角色分配权限和自定义权限,取的是并集,把重复的权限过滤掉
20、路由懒加载实现
1、安装 @babel/plugin-syntax-dynamic-import 包
2、在babel.config.js配置文件中声明该插件
<以上是关于前端常见面试题的主要内容,如果未能解决你的问题,请参考以下文章