2020web前端面试总结(建议收藏)

1,117 阅读40分钟

web前端全栈资料粉丝福利(面试题、视频、资料笔记,进阶路线)

一、CSS问题1.flex布局

display:flex; 在父元素设置,子元素受弹性盒影响,默认排成一行,如果超出一行,按比例压缩 flex:1; 子元素设置,设置子元素如何分配父元素的空间,flex:1,子元素宽度占满整个父元素align-items:center 定义子元素在父容器中的对齐方式,center 垂直居中justify-content:center 设置子元素在父元素中居中,前提是子元素没有把父元素占满,让子元素水平居中。

2.css3的新特性

transtion transition-property 规定设置过渡效果的 CSS 属性的名称。
transition-duration 规定完成过渡效果需要多少秒或毫秒。
transition-timing-function 规定速度效果的速度曲线。
transition-delay 定义过渡效果何时开始。
animation属性可以像Flash制作动画一样,通过控制关键帧来控制动画的每一步,实现更为复杂的动画效果。
ainimation实现动画效果主要由两部分组成:
通过类似Flash动画中的帧来声明一个动画;
在animation属性中调用关键帧声明的动画。
translate 3D建模效果

3.img中alt和title的区别

图片中的 alt属性是在图片不能正常显示时出现的文本提示。alt有利于SEO优化
图片中的 title属性是在鼠标在移动到元素上的文本提示。

4.用纯CSS创建一个三角形

 <style>
    div {
        width: 0;
        height: 0;
        border-top: 40px solid transparent;
        border-left: 40px solid transparent;
        border-right: 40px solid transparent;
        border-bottom: 40px solid #ff0000;
    }
    </style>
</head>
<body>
  <div></div>
</body>

5.如何理解CSS的盒子模型?

标准盒子模型:宽度=内容的宽度(content)+ border + padding
低版本IE盒子模型:宽度=内容宽度(content+border+padding)

6.如何让一个div水平居中

已知宽度,block元素 ,添加添加margin:0 auto属性。
已知宽度,绝对定位的居中 ,上下左右都为0,margin:auto

7.如何让一个div水平垂直居中

div {
position: relative / fixed; /* 相对定位或绝对定位均可 */
width:500px;
height:300px;
top: 50%;
left: 50%;
margin-top:-150px;
margin-left:-250px;
 外边距为自身宽高的一半 */
background-color: pink; /* 方便看效果 */
 }

.container {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
 
}
.container div {
width: 100px; /* 可省 */
height: 100px; /* 可省 */
background-color: pink; /* 方便看效果 */
}  

8.如何清除浮动?

clear清除浮动(添加空div法)在浮动元素下方添加空div,并给该元素写css样式 {clear:both;height:0;overflow:hidden;}
给浮动元素父级设置高度
父级同时浮动(需要给父级同级元素添加浮动)
父级设置成inline-block,其margin: 0 auto居中方式失效
给父级添加overflow:hidden 清除浮动方法
万能清除法 after伪类 清浮动(现在主流方法,推荐使用)
float_div:after{
content:".";
clear:both;
display:block;
height:0;
overflow:hidden;
visibility:hidden;
}
.float_div{
zoom:1
}

9.css3实现三栏布局,左右固定,中间自适应

圣杯布局/双飞翼布局
 <style>
        * {
            margin: 0;
            padding: 0;
        }
        .middle,
        .left,
        .right {
            position: relative;
            float: left;
            min-height: 130px;
        }
        .container {
            padding: 0 220px 0 200px;
            overflow: hidden;
        }
        .left {
            margin-left: -100%;
            left: -200px;
            width: 200px;
            background: red;
        }
        .right {
            margin-left: -220px;
            right: -220px;
            width: 220px;
            background: green;
        }
        .middle {
            width: 100%;
            background: blue;
            word-break: break-all;
        }
    </style>
</head>
<body>
    <div class='container'>
        <div class='middle'></div>
        <div class='left'></div>
        <div class='right'></div>
    </div>
</body>


10.display:none 和 visibility: hidden的区别

display:none 隐藏对应的元素,在文档布局中不再给它分配空间,它各边的元素会合拢,就当他从来不存在。
visibility:hidden 隐藏对应的元素,但是在文档布局中仍保留原来的空间。

11.CSS中 link 和@import 的区别是?

link属于HTML标签,而@import是CSS提供的页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载
import只在IE5以上才能识别,而link是HTML标签,无兼容问题
link方式的样式的权重 高于@import的权重.

12.position的absolute与fixed共同点与不同点

共同点: 改变行内元素的呈现方式,display被置为block 让元素脱离普通流,不占据空间 默认会覆盖到非定位元素上
不同点: absolute的”根元素“是可以设置的 fixed的”根元素“固定为浏览器窗口。当你滚动网页,fixed元素与浏览器窗口之间的距离是不变的。

13..transition和animation的区别

Animation和transition大部分属性是相同的,他们都是随时间改变元素的属性值,他们的主要区别是transition需要触发一个事件才能改变属性, 而animation不需要触发任何事件的情况下才会随时间改变属性值,并且transition为2帧,从from .... to,而animation可以一帧一帧的。
transition 规定动画的名字 规定完成过渡效果需要多少秒或毫秒 规定速度效果 定义过渡效果何时开始 animation 指定要绑定到选择器的关键帧的名称

14.CSS优先级

不同级别:总结排序:!important > 行内样式>ID选择器 > 类选择器 > 标签 > 通配符 > 继承 > 浏览器默认属性
	1.属性后面加!import 会覆盖页面内任何位置定义的元素样式
	2.作为style属性写在元素内的样式
	3.id选择器
	4.类选择器
	5.标签选择器
	6.通配符选择器(*)
	7.浏览器自定义或继承
**同一级别:后写的会覆盖先写的**
css选择器的解析原则:选择器定位DOM元素是从右往左的方向,这样可以尽早的过滤掉一些不必要的样式规则和元素

15.雪碧图:

多个图片集成在一个图片中的图
使用雪碧图可以减少网络请求的次数,加快允许的速度
通过background-position,去定位图片在屏幕的哪个位置


二、JS问题1.typeof和instance of 检测数据类型有什么区别?

相同点: 都常用来判断一个变量是否为空,或者是什么类型的。
不同点: typeof 返回值是一个字符串,用来说明变量的数据类型 instanceof 用于判断一个变量是否属于某个对象的实例.


16.使元素消失的方法

多个图片集成在一个图片中的图
使用雪碧图可以减少网络请求的次数,加快允许的速度
通过background-position,去定位图片在屏幕的哪个位置

.谈一谈深克隆和浅克隆?

浅克隆: 只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“(浅复制)浅拷贝”,换句话说,浅复制仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么浅复制出来的对象也会相应改变。
深克隆: 创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
JSON.parse、JSON.stringify()

3.es6的新特性都有哪些?

let定义块级作用域变量 没有变量的提升,必须先声明后使用 let声明的变量,不能与前面的let,var,conset声明的变量重名
const 定义只读变量 const声明变量的同时必须赋值,const声明的变量必须初始化,一旦初始化完毕就不允许修改 const声明变量也是一个块级作用域变量 const声明的变量没有“变量的提升”,必须先声明后使用 const声明的变量不能与前面的let, var , const声明的变量重 const定义的对象\数组中的属性值可以修改,基础数据类型不可以
ES6可以给形参函数设置默认值
在数组之前加上三个点(...)展开运算符
数组的解构赋值、对象的解构赋值
箭头函数的特点 箭头函数相当于匿名函数,是不能作为构造函数的,不能被new 箭头函数没有arguments实参集合,取而代之用...剩余运算符解决 箭头函数没有自己的this。他的this是继承当前上下文中的this 箭头函数没有函数原型 箭头函数不能当做Generator函数,不能使用yield关键字 不能使用call、apply、bind改变箭头函数中this指向 Set数据结构,数组去重

4.==和===区别是什么?

=赋值
==返回一个布尔值;相等返回true,不相等返回false; 允许不同数据类型之间的比较; 如果是不同类型的数据进行,会默认进行数据类型之间的转换; 如果是对象数据类型的比较,比较的是空间地址
=== 只要数据类型不一样,就返回false;

5.常见的设计模式有哪些?

1、js工厂模式
2、js构造函数模式
3、js原型模式
4、构造函数+原型的js混合模式
5、构造函数+原型的动态原型模式
6、观察者模式
7、发布订阅模式

6.call bind apply 的区别?

call() 和apply()的第一个参数相同,就是指定的对象。这个对象就是该函数的执行上下文。
call()和apply()的区别就在于,两者之间的参数。
call()在第一个参数之后的 后续所有参数就是传入该函数的值。
apply() 只有两个参数,第一个是对象,第二个是数组,这个数组就是该函数的参数。 bind() 方法和前两者不同在于: bind() 方法会返回执行上下文被改变的函数而不会立即执行,而前两者是 直接执行该函数。他的参数和call()相同。

7.js继承方式有哪些?

原型链继承 核心: 将父类的实例作为子类的原型
构造继承 核心:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类
实例继承 核心:为父类实例添加新特性,作为子类实例返回
拷贝继承
组合继承 核心:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现 函数复用
寄生组合继承 核心:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实 例方法/属性,避免的组合继承的缺点

8.你怎样看待闭包?

个人感觉,简单来说闭包就是在函数里面声明函数,本质上说就是在函数内部和函数外部搭建起一座桥梁,使得子函数可以访问父函数中所有的局部变量,但是反之不可以,这只是闭包的作用之一,另一个作用,则是保护变量不受外界污染,使其一直存在内存中,在工作中我们还是少使用闭包的好,因为闭包太消耗内存,不到万不得已的时候尽量不使用。

9.你是如何理解原型和原型链的?

把所有的对象共用的属性全部放在堆内存的一个对象(共用属性组成的对象),然后让每一个对象的 __proto__存储这个「共用属性组成的对象」的地址。而这个共用属性就是原型,原型出现的目的就是为了减少不必要的内存消耗。而原型链就是对象通过__proto__向当前实例所属类的原型上查找属性或方法的机制,如果找到Object的原型上还是没有找到想要的属性或者是方法则查找结束,最终会返回undefined

10.浏览器渲染的主要流程是什么?

将html代码按照深度优先遍历来生成DOM树。 css文件下载完后也会进行渲染,生成相应的CSSOM。 当所有的css文件下载完且所有的CSSOM构建结束后,就会和DOM一起生成Render Tree。 接下来,浏览器就会进入Layout环节,将所有的节点位置计算出来。 最后,通过Painting环节将所有的节点内容呈现到屏幕上。

11.从输入url地址到页面相应都发生了什么?

1、浏览器的地址栏输入URL并按下回车。
2、浏览器查找当前URL是否存在缓存,并比较缓存是否过期。3、DNS解析URL对应的IP。
4、根据IP建立TCP连接(三次握手)。
5、HTTP发起请求。
6、服务器处理请求,浏览器接收HTTP响应。
7、渲染页面,构建DOM树。
8、关闭TCP连接(四次挥手)

12.session、cookie、localStorage的区别

相同点 都是保存在浏览器端,且同源的。
不同点

cookie数据始终在同源的http请求中携带,即cookie在浏览器和服务器间来回传递。
而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。
cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下。 存储大小限制也不同,cookie数据不能超过4k,同时因为每次http请求都会携带cookie,所以cookie只适合保存很小的数据。
sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。 数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;
localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;
cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。 作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;
localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。

13.js中跨域方法

同源策略(协议+端口号+域名要相同)
1、jsonp跨域(只能解决get) 原理:动态创建一个script标签。利用script标签的src属性不受同源策略限制,因为所有的src属性和href属性都不受同源策略的限制,可以请求第三方服务器资源内容
步骤: 1).去创建一个script标签 2).script的src属性设置接口地址 3).接口参数,必须要带一个自定义函数名,要不然后台无法返回数据 4).通过定义函数名去接受返回的数据
2、document.domain 基础域名相同 子域名不同
3、window.name 利用在一个浏览器窗口内,载入所有的域名都是共享一个window.name
4、服务器设置对CORS的支持 原理:服务器设置Access-Control-Allow-Origin HTTP响应头之后,浏览器将会允许跨域请求
5、利用h5新特性window.postMessage()

14.前端有哪些页面优化方法?

  • 减少 HTTP请求数
  • 从设计实现层面简化页面
  • 合理设置 HTTP缓存
  • 资源合并与压缩
  • 合并 CSS图片,减少请求数的又一个好办法。
  • 将外部脚本置底(将脚本内容在页面信息内容加载后再加载)
  • 多图片网页使用图片懒加载。
  • 在js中尽量减少闭包的使用
  • 尽量合并css和js文件
  • 尽量使用字体图标或者SVG图标,来代替传统的PNG等格式的图片
  • 减少对DOM的操作
  • 在JS中避免“嵌套循环”和 “死循环”
  • 尽可能使用事件委托(事件代理)来处理事件绑定的操作


15.Ajax的四个步骤

1.创建ajax实例
2.执行open 确定要访问的链接 以及同步异步
3.监听请求状态
4.发送请求

16.数组去重的方法

ES6的set对象 先将原数组排序,在与相邻的进行比较,如果不同则存入新数组
function unique(arr){
    var arr2 = arr.sort();
    var res = [arr2[0]];
    for(var i=1;i<arr2.length;i++){
        if(arr2[i] !== res[res.length-1]){
        res.push(arr2[i]);
    }
}
return res;
}
利用下标查询
 function unique(arr){
    var newArr = [arr[0]];
    for(var i=1;i<arr.length;i++){
        if(newArr.indexOf(arr[i]) == -1){
        newArr.push(arr[i]);
    }
}
return newArr;
}


17.ajax中get和post请求的区别

  • get 一般用于获取数据
  • get请求如果需要传递参数,那么会默认将参数拼接到url的后面;然后发送给服务器;
  • get请求传递参数大小是有限制的;是浏览器的地址栏有大小限制;
  • get安全性较低
  • get 一般会走缓存,为了防止走缓存,给url后面每次拼的参数不同;放在?后面,一般用个时间戳
  • post 一般用于发送数据
  • post传递参数,需要把参数放进请求体中,发送给服务器;
  • post请求参数放进了请求体中,对大小没有要求;
  • post安全性比较高;
  • post请求不会走缓存;

18.ajax的状态码

2开头

200 : 代表请求成功;
3开头

301 : 永久重定向;
302: 临时转移
304 : 读取缓存 [表示浏览器端有缓存,并且服务端未更新,不再向服务端请求资源]
307:临时重定向
以4开头的都是客户端的问题;

400 :数据/格式错误
401: 权限不够;(身份不合格,访问网站的时候,登录和不登录是不一样的)
404 : 路径错误,找不到文件
以5开头都是服务端的问题

500 : 服务器的问题
503: 超负荷;

19.移动端的兼容问题

给移动端添加点击事件会有300S的延迟 如果用点击事件,需要引一个fastclick.js文件,解决300s的延迟 一般在移动端用ontouchstart、ontouchmove、ontouchend
移动端点透问题,touchstart 早于 touchend 早于click,click的触发是有延迟的,这个时间大概在300ms左右,也就是说我们tap触发之后蒙层隐藏, 此时 click还没有触发,300ms之后由于蒙层隐藏,我们的click触发到了下面的a链接上 尽量都使用touch事件来替换click事件。例如用touchend事件(推荐)。 用fastclick,github.com/ftlabs/fast… 用preventDefault阻止a标签的click 消除 IE10 里面的那个叉号 input:-ms-clear{display:none;}
设置缓存 手机页面通常在第一次加载后会进行缓存,然后每次刷新会使用缓存而不是去重新向服务器发送请求。如果不希望使用缓存可以设置no-cache。
圆角BUG 某些Android手机圆角失效 background-clip: padding-box; 防止手机中网页放大和缩小 这点是最基本的,做为手机网站开发者来说应该都知道的,就是设置meta中的viewport
设置用户截止缩放,一般写视口的时候就已经写好了。

20.JS中同步和异步,以及js的事件流

同步:在同一时间内做一件事情
异步:在同一时间内做多个事情 JS是单线程的,每次只能做一件事情,JS运行在浏览器中,浏览器是多线程的,可以在同一时间执行多个任务。

21.JS中常见的异步任务

定时器、ajax、事件绑定、回调函数、async await、promise

22.TCP的三次握手和四次挥手

三次握手

第一次握手:客户端发送一个SYN码给服务器,要求建立数据连接;
第二次握手: 服务器SYN和自己处理一个SYN(标志);叫SYN+ACK(确认包);发送给客户端,可以建立连接
第三次握手: 客户端再次发送ACK向服务器,服务器验证ACK没有问题,则建立起连接;
四次挥手

第一次挥手: 客户端发送FIN(结束)报文,通知服务器数据已经传输完毕;
第二次挥手: 服务器接收到之后,通知客户端我收到了SYN,发送ACK(确认)给客户端,数据还没有传输完成
第三次挥手: 服务器已经传输完毕,再次发送FIN通知客户端,数据已经传输完毕
第四次挥手: 客户端再次发送ACK,进入TIME_WAIT状态;服务器和客户端关闭连接;


23.为什么建立连接是三次握手,而断开连接是四次挥手呢?

建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。 而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。

24.DOM diff原理

  • 如果元素类型发生变化,直接替换
  • 如果是文本,则比较文本里面的内容,是否有差异,如果是元素就需要比较当前元素的属性是否相等,会先比较key, 在比较类型 为什么 react中循环 建议不要使用索引 ,如果纯为了展示 那可以使用索引

25.作用域


全局作用域

  • 浏览器打开一个页面时,浏览器会给JS代码提供一个全局的运行环境,那么这个环境就是全局作用域 一个页面只有一个全局作用域,全局作用域下有一个window对象 window是全局作用域下的最大的一个内置对象(全局作用域下定义的变量和函数都会存储在window下) 如果是全局变量,都会给window新增一个键值对;属性名就是变量名,属性值就是变量所存储的值 如果变量只被var过,那么存储值是undefined 在私有作用域中是可以获取到全局变量的,但是在全局作用域中不能获取私有变量

私有作用域

  • 函数执行会形成一个新的私有的作用域(执行多次,形成多个私有作用域) 私有作用域在全局作用域中形成,具有包含的关系; 在一个全局作用域中,可以有很多个私有作用域 在私有作用域下定义的变量都是私有变量 形参也是私有变量 函数体中通过function定义的函数也是私有的,在全局作用域不能使用;

块级作用域

  • es6中新引入的一种作用域 在js中常见到的if{}、for{}、while{}、try{}、catch{}、switch case{}都是块级作用域 var obj = {} //对象的大括号不是块级作用域 块级作用域中的同一变量不能被重复声明(块级下var和function不能重名,否则会报错) 作用域链

上级作用域

  • 函数在哪里定义,他的上一级作用域就是哪,和函数在哪个作用域下执行没有关系 作用域链:当获取变量所对应的值时,首先看变量是否是私有变量,如果不是私有变量,要继续向上一级作用域中查找,如果上一级也没有,那么会继续向上一级查找,直到找到全局作用域为止;如果全局作用域也没有,则会报错;这样一级一级向上查找,就会形成作用域链 当前作用域没有的,则会继续向上一级作用域查找 当前函数的上一级作用域跟函数在哪个作用域下执行没有关系,只跟函数在哪定义有关(重点)

26.Promise处理异步

他是ES6中新增加的一个类(new Promise),目的是为了管理JS中的异步编程的,所以把他称为“Promise设计模式” new Promise 经历三个状态:padding(准备状态:初始化成功、开始执行异步的任务)、fullfilled(成功状态)、rejected(失败状态)== Promise本身是同步编程的,他可以管理异步操作的(重点),new Promise的时候,会把传递的函数立即执行 Promise函数天生有两个参数,resolve(当异步操作执行成功,执行resolve方法),rejected(当异步操作失败,执行reject方法) then()方法中有两个函数,第一个传递的函数是resolve,第二个传递的函数是reject ajax中false代表同步,true代表异步,如果使用异步,不等ajax彻底完成


27.map和forEach的区别

相同点

都是循环遍历数组中的每一项 forEach和map方法里每次执行匿名函数都支持3个参数,参数分别是item(当前每一项)、index(索引值)、arr(原数组),需要用哪个的时候就写哪个 匿名函数中的this都是指向window 只能遍历数组
不同点

map方法返回一个新的数组,数组中的元素为原始数组调用函数处理后的值。(原数组进行处理之后对应的一个新的数组。) map()方法不会改变原始数组 map()方法不会对空数组进行检测 forEach()方法用于调用数组的每个元素,将元素传给回调函数.(没有return,返回值是undefined)
注意:forEach对于空数组是不会调用回调函数的。

28.async await函数

async/await函数是异步代码的新方式
async/await是基于promise实现的
async/await使异步代码更像同步代码
await 只能在async函数中使用,不能再普通函数中使用,要成对出现
默认返回一个promise实例,不能被改变
await下面的代码是异步,后面的代码是同步的

29.this指向

全局作用域下的this指向window
如果给元素的事件行为绑定函数,那么函数中的this指向当前被绑定的那个元素
函数中的this,要看函数执行前有没有 . , 有 . 的话,点前面是谁,this就指向谁,如果没有点,指向window
自执行函数中的this永远指向window
定时器中函数的this指向window
构造函数中的this指向当前的实例
call、apply、bind可以改变函数的this指向
箭头函数中没有this,如果输出this,就会输出箭头函数定义时所在的作用域中的this

30.原型

所有的函数数据类型都天生自带一个prototype属性,该属性的属性值是一个对象 prototype的属性值中天生自带一个constructor属性,其constructor属性值指向当前原型所属的类 所有的对象数据类型,都天生自带一个_proto_属性,该属性的属性值指向当前实例所属类的原型

31.异步回调(如何解决回调地狱)

promise、generator、async/await

promise: 1.是一个对象,用来传递异步操作的信息。代表着某个未来才会知道结果的时间,并未这个事件提供统一的api,供进异步处理
	  2.有了这个对象,就可以让异步操作以同步的操作的流程来表达出来,避免层层嵌套的回调地狱
	  3.promise代表一个异步状态,有三个状态pending(进行中),Resolve(以完成),Reject(失败)
	  4.一旦状态改变,就不会在变。任何时候都可以得到结果。从进行中变为以完成或者失败
		promise.all() 里面状态都改变,那就会输出,得到一个数组
		promise.race() 里面只有一个状态变为rejected或者fulfilled即输出
		promis.finally()不管指定不管Promise对象最后状态如何,都会执行的操作(本质上还是then方法的特例)


32.前端事件流

事件流描述的是从页面中接受事件的顺序,事件 捕获阶段 处于目标阶段 事件冒泡阶段 addeventListener 最后这个布尔值参数如果是true,表示在捕获阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序。
  1、事件捕获阶段:实际目标div在捕获阶段不会接受事件,也就是在捕获阶段,事件从document到<html>再到<body>就停止了。
      2、处于目标阶段:事件在div发生并处理,但是事件处理会被看成是冒泡阶段的一部分。
      3、冒泡阶段:事件又传播回文档
   阻止冒泡事件event.stopPropagation()
	  function stopBubble(e) {
    		if (e && e.stopPropagation) { // 如果提供了事件对象event 这说明不是IE浏览器
      		e.stopPropagation()
    		} else {
      		window.event.cancelBubble = true //IE方式阻止冒泡
    	      }
  		   }
   阻止默认行为event.preventDefault()
 function stopDefault(e) {
    if (e && e.preventDefault) {
      e.preventDefault()
    } else {
      // IE浏览器阻止函数器默认动作的行为
      window.event.returnValue = false
    }
  }


33.事件如何先捕获后冒泡?

在DOM标准事件模型中,是先捕获后冒泡。但是如果要实现先冒泡后捕获的效果, 对于同一个事件,监听捕获和冒泡,分别对应相应的处理函数,监听到捕获事件,先暂缓执行,直到冒泡事件被捕获后再执行捕获事件。

哪些事件不支持冒泡事件:鼠标事件:mouserleave mouseenter 焦点事件:blur focus UI事件:scroll resize

34. 如何判断一个变量是对象还是数组(prototype.toString.call())。

千万不要使用typeof来判断对象和数组,因为这种类型都会返回object。

typeOf()是判断基本类型的Boolean,Number,symbol, undefined, String。 对于引用类型:除function,都返回object null返回object。
installOf() 用来判断A是否是B的实例,installof检查的是原型。
toString() 是Object的原型方法,对于 Object 对象,直接调用 toString() 就能返回 [Object Object] 。而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。
hasOwnProperty()方法返回一个布尔值,指示对象自身属性中是否具有指定的属性,该方法会忽略掉那些从原型链上继承到的属性。
isProperty()方法测试一个对象是否存在另一个对象的原型链上。

35.setTimeout 和 setInterval的机制

因为js是单线程的。浏览器遇到etTimeout 和 setInterval会先执行完当前的代码块,在此之前会把定时器推入浏览器的
待执行时间队列里面,等到浏览器执行完当前代码之后会看下事件队列里有没有任务,有的话才执行定时器里的代码


36.splice和slice、map和forEach、 filter()、reduce()的区别

 1.slice(start,end):方法可以从已有数组中返回选定的元素,返回一个新数组,
 包含从start到end(不包含该元素)的数组方法
	注意:该方法不会更新原数组,而是返回一个子数组
 2.splice():该方法想或者从数组中添加或删除项目,返回被删除的项目。(该方法会改变原数组)
	splice(index, howmany,item1,...itemx)
		·index参数:必须,整数规定添加或删除的位置,使用负数,从数组尾部规定位置
		·howmany参数:必须,要删除的数量,
		·item1..itemx:可选,向数组添加新项目
3.map():会返回一个全新的数组。使用于改变数据值的时候。会分配内存存储空间数组并返回,forEach()不会返回数据
4.forEach(): 不会返回任何有价值的东西,并且不打算改变数据,单纯的只是想用数据做一些事情,他允许callback更改原始数组的元素
5.reduce(): 方法接收一个函数作为累加器,数组中的每一个值(从左到右)开始缩减,最终计算一个值,不会改变原数组的值
6.filter(): 方法创建一个新数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。它里面通过function去做处理	

VUE问题1.聊聊对vue的理解

vue是一个渐进式的JS框架。他易用,灵活,高效; 可以把一个页面分隔成多个组件;当其他页面有类似功能时,直接让封装的组件进行复用; 他是构建用户界面的声明式框架,只关心图层;不关心具体是如何实现的

2.V-model的原理是什么?

Vue的双向数据绑定是由数据劫持结合发布者订阅者实现的。 数据劫持是通过Object.defineProperty()来劫持对象数据的setter和getter操作。 在数据变动时作你想做的事

原理 通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化->视图更新 在初始化vue实例时,遍历data这个对象,给每一个键值对利用Object.definedProperty对data的键值对新增get和set方法,利用了事件监听DOM的机制,让视图去改变数据

3.谈谈对生命周期的理解

  • beforeCreate阶段:vue实例的挂载元素el和数据对象data都是undefined,还没有初始化。
  • created阶段:vue实例的数据对象data有了,可以访问里面的数据和方法,未挂载到DOM,el还没有
  • beforeMount阶段:vue实例的el和data都初始化了,但是挂载之前为虚拟的dom节点
  • mounted阶段:vue实例挂载到真实DOM上,就可以通过DOM获取DOM节点
  • beforeUpdate阶段:响应式数据更新时调用,发生在虚拟DOM打补丁之前,适合在更新之前访问现有的DOM,比如手动移除已添加的事件监听器
  • updated阶段:虚拟DOM重新渲染和打补丁之后调用,组成新的DOM已经更新,避免在这个钩子函数中操作数据,防止死循环
  • beforeDestroy阶段:实例销毁前调用,实例还可以用,this能获取到实例,常用于销毁定时器,解绑事件
  • destroyed阶段:实例销毁后调用,调用后所有事件监听器会被移除,所有的子实例都会被销毁


4.VUE和REACT有什么区别?

react整体是函数式的思想,把组件设计成纯组件,状态和逻辑通过参数传入,所以在react中,是单向数据流;
vue的思想是响应式的,也就是基于是数据可变的,通过对每一个属性建立Watcher来监听,当属性变化的时候,响应式的更新对应的虚拟dom。

5.vuex的流程

页面通过mapAction异步提交事件到action。action通过commit把对应参数同步提交到mutation。
mutation会修改state中对于的值。 最后通过getter把对应值跑出去,在页面的计算属性中
通过mapGetter来动态获取state中的值


6.vuex有哪几种状态和属性

  • state中保存着共有数据,数据是响应式的
  • getter可以对state进行计算操作,主要用来过滤一些数据,可以在多组件之间复用
  • mutations定义的方法动态修改state中的数据,通过commit提交方法,方法必须是同步的
  • actions将mutations里面处理数据的方法变成异步的,就是异步操作数据,通store.dispatch来分发actions,把异步的方法写在actions中,通过commit提交mutations,进行修改数据。
  • modules:模块化vuex

7.vue路由的两种模式

  • hash ——即地址栏URL中的#符号(此hsah 不是密码学里的散列运算) hash 虽然出现URL中,但不会被包含在HTTP请求中,对后端完全没有影响,因此改变hash不会重新加载页面。
  • history ——利用了HTML5 History Interface 中新增的pushState() 和replaceState() 方法

这两个方法应用于浏览器的历史记录站,在当前已有的back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改是,虽然改变了当前的URL,但你浏览器不会立即向后端发送请求。

8.vue中 key 值的作用

当 Vue.js 用v-for正在更新已渲染过的元素列表时,它默认用“就地复用”策略。 如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。
key的作用主要是为了高效的更新虚拟DOM。

9$route和$router的区别

  • $route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。
  • $router是“路由实例”对象包括了路由的跳转方法,钩子函数等。

10.vue-router守卫

  • 导航守卫 router.beforeEach 全局前置守卫
  • to: Route: 即将要进入的目标(路由对象)
  • from: Route: 当前导航正要离开的路由
  • next: Function: 一定要调用该方法来 resolve 这个钩子。(一定要用这个函数才能去到下一个路由,如果不用就拦截) 执行效果依赖 next 方法的调用参数。
  • next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
  • next(false): 取消进入路由,url地址重置为from路由地址(也就是将要离开的路由地址)。


// main.js 入口文件
    import router from './router'; // 引入路由
    router.beforeEach((to, from, next) => { 
      next();
    });
    router.beforeResolve((to, from, next) => {
      next();
    });
    router.afterEach((to, from) => {
      console.log('afterEach 全局后置钩子');
    });


组件内的守卫 你可以在路由组件内直接定义以下路由导航守卫

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

组件内的守卫 你可以在路由组件内直接定义以下路由导航守卫

const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
  },
  beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用,我们用它来禁止用户离开
    // 可以访问组件实例 `this`
    // 比如还未保存草稿,或者在用户离开前,
    将setInterval销毁,防止离开之后,定时器还在调用。
  }
}


11.axios是什么?怎么使用?描述使用它实现登录功能的流程?

请求后台资源的模块。
$ npm install axios -S装好 复制代码
然后发送的是跨域,需在配置文件中config/index.js进行设置。后台如果是Tp5则定义一个资源路由。 js中使用import进来,然后.get或.post。返回在.then函数中如果成功,失败则是在.catch函数中

12.vue修饰符

  • stop:阻止事件的冒泡
  • prevent:阻止事件的默认行为
  • once:只触发一次
  • self:只触发自己的事件行为时,才会执行

13.vue项目中的性能优化


1.不要在模板里面写过多表达式
2.循环调用子组件时添加key
3.频繁切换的使用v-show,不频繁切换的使用v-if
4.尽量少用float,可以用flex
5.按需加载,可以用require或者import()按需加载需要的组件
6.路由懒加载

14.vue.extend和vue.component

  • extend 是构造一个组件的语法器。 然后这个组件你可以作用到Vue.component这个全局注册方法里 还可以在任意vue模板里使用组件。 也可以作用到vue实例或者某个组件中的components属性中并在内部使用apple组件。
  • Vue.component 你可以创建 ,也可以取组件。

常见的兼容问题

png24位的图片在iE6浏览器上出现背景 解决方案是做成PNG8.也可以引用一段脚本处理.

浏览器默认的margin和padding不同。 解决方案是加一个全局的*{margin:0;padding:0;}来统一。

IE6双边距bug:块属性标签float后,又有横行的margin情况下,在ie6显示margin比设置的大。

浮动ie产生的双倍距离(IE6双边距问题:在IE6下,如果对元素设置了浮动,同时又设置了margin-left或margin-right,margin值会加倍。) #box{ float:left; width:10px; margin:0 0 0 100px;}

React问题1.react和vue的区别

=> 相同点:
1.数据驱动页面,提供响应式的试图组件
2.都有virtual DOM,组件化的开发,通过props参数进行父子之间组件传递数据,都实现了webComponents规范
3.数据流动单向,都支持服务器的渲染SSR
4.都有支持native的方法,react有React native, vue有wexx
=> 不同点:
1.数据绑定:Vue实现了双向的数据绑定,react数据流动是单向的
2.数据渲染:大规模的数据渲染,react更快
3.使用场景:React配合Redux架构适合大规模多人协作复杂项目,Vue适合小快的项目
4.开发风格:react推荐做法jsx + inline style把html和css都写在js了
vue是采用webpack + vue-loader单文件组件格式,html, js, css同一个文件


2.redux中的reducer(纯函数)

Redux数据流里,reduces其实是根据之前的状态(previous state)和现有的action(current action)
更新state(这个state可以理解为上下累加器的结果)
每次redux reducer被执行时,state和action被传入,这个state根据action进行累加或者是'自身消减'(reduce),
进而返回最新的state,这也就是典型reduce函数的用法:state ->  action ->  state


3.react的refs

refs就想一个逃生窗,允许我们之间访问dom元素或者组件实例,可以向组件添加一个ref属性的值是一个回调函数,
它将接受地城dom元素或组件的已挂在实例,作为第一个参数

4.react中的keys

帮组我们跟踪哪些项目已更改、添加、从列表中删除,key是独一无二的,可以让我们高效的去定位元素,并且操作它

5.React的生命周期

三个状态:Mounting(已插入真实的DOM)
	  Updating(正在被重新渲染)
	  Unmounting(已移除真实的DOM)
componentDIdMount 在第一次渲染后调用,只在客服端。之后组件已经生成对应的DOM结构,
componentDidUpdate 在组件完成更新后立即调用,在出初始化是不会调用


6.React子组件向父组件传值

父组件通过props 给子组件传递数据,子组件则是通过调用父组件传给它的函数给父组件传递数据。


7.为什么虚拟DOM会提高性能 www.zhihu.com/question/29…

虚拟DOM相当于在js和真实dom中间加了一个缓存,利用dom diff算法避免了没有必要的doom操作,从而提高性能
具体实现步骤:
·用JavaScript对象结构表示DOM树的结构;然后用这个树构建一个真正的DOM树,插到文档中
·当状态变更的时候,重新构造一棵树的对象树,然后用新的树和旧的树进行对比,记录两棵树差异
·把2所记录的差异应用到步骤1所构建的真正的DOM树上,试图就更新了。

8.diff算法

1.把树形结构按照层级分解,只比较同级元素
2.给列表结构的每个单元添加key属性,方便比较。在实际代码中,会对新旧两棵树进行一个深度优先的遍历,这样每个节点都会有一个标记
3.在深度优先遍历的时候,每遍历到一个节点就把该节点和新的树进行对比。如果有差异的话就记录到一个对象里面
Vritual DOM 算法主要实现上面步骤的三个函数:element, diff, patch。然后就可以实际的进行使用
react只会匹配相同的class的component(这里的class指的是组件的名字)
合并操作,条用component的setState方法的时候,React将其标记为dirty.到每一个时间循环借宿,React检查所有标记dirty的component重新绘制
4.选择性子树渲染。可以重写shouldComponentUpdate提高diff的性能	


9.简述下flux的思想

flux的最大特点,就是数据的‘单向流动’ 1.用户访问View 2.View发出用户的Action 3.Dispatcher收到Action,要求state进行相应的更新 4.store更新后,发出一个‘change’事件后,更新页面

10.reac性能优化是哪个周期函

shouldComponentUpdate 这个方法用来判断是否需要调用render方法重新描绘dom.因为dom的描绘非常消耗性能, 如果我们在shouldComponentUpdate方法中能够写出更优化的dom diff算法,可以极大的提高性能

11.react怎么划分业务组件和技术组件

根据组件的职责通常把组件分为UI组件和容器组件 UI组件负责UI的呈现,容器组件负责管理数据和逻辑 两者通过React-redux提供connect方法联系起来

12.setState

setState通过一个队列机制实现state更新,当执行setState时,会将需要更新的state很后放入状态队列
而不会立即更新this.state,队列机制可以高效地批量更新state。如果不通过setState而直接修改this.state的值	
那么该state将不会被放入状态队列中。当下次调用setState并对状态队列进行合并时,就会忽略之前修改的state,造成不可预知的错误

同时,也利用了队列机制实现了setState的异步更新,避免了频繁的重复更新state

同步更新state:
	setState 函数并不会阻塞等待状态更新完毕,因此 setNetworkActivityIndicatorVisible 有可能先于数据渲染完毕就执行。
	第二个参数是一个回调函数,在setState的异步操作结束并且组件已经重新渲染的时候执行
	也就是说,我们可以通过这个回调来拿到更新的state的值,实现代码的同步

例子:componentDidMount() {

	fetch('https://test.com')
    
	.then((res) => res.json())
    
	.then(
    (data) => {
this.setState({ data:data });
			StatusBar.setNetworkActivityIndicatorVisible(false);
        }