敲敲敲复习总汇

570 阅读32分钟

hello,大家好,我是disguiseFish!以下是我做前端这些年平时学习和面试的总结笔记,最近想把它分享出来,写的很杂也不是那么深入,如果有什么错误的地方,希望有小伙伴指出来,如果对你有帮助那就更好了,希望我们都能朝着自己的目标前进。加油! ---- 2018年的学习笔记

1 同源策略

所谓同源策略,指的是浏览器对不同源的浏览器的访问方式进行的限制 而重定向以及表单提交不会受到同源策略的限制,允许跨域资源的嵌入

2 如何解决跨域 什么是跨域 什么情况会发生跨域?

跨域: 浏览器从一个域名的网页去请求另一个域名的资源时,域名端口协议任一不同;
如何解决跨域: jsonp cors nginx代理跨域:

jsonp :
1 前端定义好一个方法,通过script的src将方法名传给后台
2 后台获取方法名后,在名字后面接(),添加json数据
3 后台再把它返回给前端,浏览器接收到方法,调用后立即执行 
 (后台再把它返回给前端相当于前端调用了,浏览器立即执行)
缺点:无法发送post请求  不能请求图片文件等等 不容易确定请求是否发送成功或者失败


CORS: 跨域资源共享
CORS需要浏览器和服务器同时支持,只要服务器实现了CORS接口,就可以跨源通信。
是现在浏览器支持跨域资源请求的最常用的一种方式,跨域行为是浏览器行为,浏览器阻止允许ajax行为,服务器之间是不存在跨域的
1 浏览器会根据同源策略查看是否是跨域请求,如果同源直接发送ajax请求
2 如果非同源就是跨域请求,浏览器会自动发送一条预检请求,服务器接收到请求后会返回请求头信息,
浏览器查看返回的响应头信息中是否设置了header
3 如果没有设置说明服务器不允许使用cors跨域,那么浏览器不会发送真正的ajax请求
4 如果设置了header,浏览器会跟请求头中的Origin进行对比,如果满足要求会发送真正的ajax请求,否则不发送

 服务器返回的响应头包含: 编码格式,允许的域名,允许方式,允许的请求头
 res.writeHead(200, {
          "Content-Type": "text/html; charset=UTF-8",
          "Access-Control-Allow-Origin":'http://localhost',
          'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
          'Access-Control-Allow-Headers': 'X-Requested-With, Content-Type'
      });

cors不就是你们后端把请求设置为*一类的吗,可以允许各种域名的请求,不过就是不安全


nginx代理跨域:
服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨域问题。
通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,
并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。
反向代理一般是运维或者后端的事情


什么情况下会发生跨域/原因: 
由于浏览器的同源策略,从一个域名的网页去请求另一个域名的资源时,会产生跨域,主要是考虑到安全性 

3 AJAX:

  AJAX从英文直译过来就是  异步的JavaScript和xml
  AJAX能快速创建动态网页,可以在无需重新加载整个网页的情况下,
  能更新部分网页(异步更新).而传统的网页在不使用Ajax的情况下想要更新内容就必须
  重新加载整个网页

  优点:
  1 不更新整个页面的前提下维护数据,减轻服务器的负担
  2 提升用户体验
  3 基于Xml标准化,不需要安装插件,被广泛支持.
  4 具有更加迅速的响应能力
  5 ajax可使   因特网应用程序   更小、更快,更友好。

  缺点:
  1 编写时需要考虑浏览器兼容性(AJAX大量的使用了javascript和ajax引擎)
  2 AJAX没有后退按钮
  3 对流媒体还有移动设备的支持不是太好
  4 安全问题 AJAX暴露了与服务器交互的细节。
  5 不容易调试。
  6 对搜索引擎的支持比较弱。

  原理:
  1 创建AJAX对象:
  AJAX的工作原理:(原生AJAX)
  var xhr = new XMLHttpRequest();   

  2 请求行:
  xhr.open("get","08.php?name=hucc");  请求方式,请求地址
  xhr.open("post","08.php");            

  3 请求头:
  xhr.setRequestHeader('content-type','text/html');  get请求可以不用设置
  xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
  post请求必须设置

  4 请求体:
  xhr.send(null)  --->get 数据列表已经拼接到url后面了
  xhr.send(data)  --->post  要将参数列表设置到请求体中

  5 监听服务器的响应:(ajax对象完成数据接收)
  判断http响应状态(status)200-300之间或者304(缓存)执行回调函数
  xhr.onreadystatechange=function(){
    readyState:请求状态为 读取服务器响应结束
    status:状态码
    if(xhr.readyState==4 && xhr.status==200){
      var r =xhr.responseText;  //获取响应主体/服务器返回的核心数据,需要渲染
      callback && callback(r);
    }
  }

  现在基本第三方的ajax的配置项中都是吧cache配置成false了,不让请求缓存呀.但是浏览器还是会缓存页面内容的

4 cookie sessionstorage localstorage 三者区别:

cookie                4K    可以设置有效期,不设置的话就是会话级别的    保存在浏览器端   cookie只能保存字符串类型,是以文本的方式保存在客户端
sessionstorage        5M    关闭窗口就删除                           保存在服务器端   session通过类似与Hashtable的数据结构来保存,能支持任何类型的对象
localstorage          5M    关闭窗口不丢失 要主动删除                 保存在本地

cookie和localStorage都是跨窗口的,即使浏览器的窗口关闭,这两个值还是存在的。
cookie和sessionstorage都是用来跟踪浏览器用户身份的会话方式。

一般来说,保存用户密码常见的两种方式是:session和cookie
session的保存方式相对来说比较安全,因为信息存储在服务器的
原因如下:(1)sessionID存储在cookie中,若要攻破session首先要攻破cookie; 
(2)sessionID是要有人登录,或者启动session_start才会有,所以攻破cookie也不一定能得到sessionID; 
(3)第二次启动session_start后,前一次的sessionID就是失效了,session过期后,sessionID也随之失效。 
(4)sessionID是加密的 
(5)综上所述,攻击者必须在短时间内攻破加密的sessionID,这很难。

而cookie的方式由于对服务器端来说是不可控的,始终对用户信息泄露是一个危险
但是也有很多采用cookie存储用户信息的,通常是采用加密的方式来进行处理
比如discuz就是采用cookie的方式存储用户信息
我们经常看到很多网站设置记住用户名密码,就是采用cookie的方式
针对cookie所存在的攻击:Cookie欺骗,Cookie截获;session的安全性大于cookie。


cookie:
1判断用户是否登录过网站以便下次登录时能够实现自动登录
(或者记住密码,如果我们删除cookie,则每次登录必须重新填写登录的相关信息)
2保存上一次登录等信息
3保存上一次查看的页面
4浏览计数
5一般存储用户名密码相关信息,一般使用escape转义编码后存储

sessionstorage:
用于保存每个用户的专用信息,变量的保存在服务器端,通过sessionID来区分不同的客户
1网上商城中的购物车
2保存用户的登录信息
3将某些数据放入sessionstorage中,供同一用户的不同页面使用
4防止用户非法登录
5统计当前页面元素的点击次数。

localStorage:
1 可以用来统计页面访问次数
2 常用于长期登录(判断用户是否已登录),适合长期保存在本地的数据
3 用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的
4 有离线操作的时候会用到,比如我们做过新闻编辑上传功能,离线可以保存,有网络直接提交

sessionStorage:敏感账号一次登录


BOM:浏览器对象模型
DOM:文档对象模型

5 http协议? 状态码?

-200:客户端请求成功
-404:请求资源不存在
-403:服务器收到请求,但拒绝提供服务,客户端出错,没有权限拒绝访问,一般可能是跨域了或者登陆有效期过了
-500:服务器发生不可预期的错误(一般是后台代码出错),服务器出错
301:永久性页面重定向
302:暂时性页面重定向
304:客户端已经执行了GET,但文件未变化--请求本地缓存 
请求的内容未被修改~后台接口不返回304,浏览器就不会从缓存中读取数据,返回304基本都是读的浏览器缓存数据
400:客户端请求有语法错误,不能被服务器所理解


http协议:
超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议
在Web应用中,服务器把网页传给浏览器,实际上就是把网页的HTML代码发送给浏览器,
让浏览器显示出来。而浏览器和服务器之间的传输协议是HTTP,所以:
HTML是一种用来定义网页的文本,会HTML,就可以编写网页;
HTTP是在网络上传输HTML的协议,用于浏览器和服务器的通信。

----不过 请求一般都会拼接上随机数   防止用缓存请求(当年做的笔记,,现在不知道啥意思了。。。?)

6 什么是闭包?

闭包是一个能够读取其他函数内部变量的函数 闭包可以简单理解成 定义在函数内部的函数 从本质上来讲,闭包是将函数内部和函数外部连接起来的桥梁; 能够对私有变量进行操作 如果一个函数被其父函数以外的变量引用,就会形成闭包

闭包的形成条件:
有两个函数,是嵌套关系,内部函数还访问了外部函数的声明和变量。

自己的理解:
一个函数嵌套一个函数,且内部函数引用外部变量就会形成闭包

闭包的3个特性:
1 函数嵌套函数
2 函数内部可以引用函数外部的参数和变量
3 参数和变量不会被垃圾回收机制回收

优点:
1 保护函数内的变量安全
2 在内存中维持一个变量 可以做缓存
3 私有成员的存在

缺点:
1 会造成内存泄漏 (解决方法:使用完变量之后手动为其赋值null)
2 增加内存使用量

7 new做了4件事情:

1 创建了一个新的空对象

2 this指向了这个新对象(给this新对象添加了属性)

3 执行构造函数(实例化属性和方法/给属性和方法赋值)

4 返回这个新对象

8 浏览器内核:

                                 提升浏览器兼容性前面要加
  ie浏览器:   Trident内核           :-ms
  Firefox:    Gecko内核             :-moz(对页面放大缩小的适配特别好又快) 
  Safari:     Webkit内核
  Opera 欧朋: Blink内核;
  Chrome:     Blink内核
  
  (opera是chrome的一个分支,所以chrome用什么opera用什么)
  

9 vue的双向数据绑定原理是什么?

vue.js是采用 数据劫持结合发布者-订阅者 模式来实现双向数据绑定的

通过Object.defineProperty()来劫持各个属性的setter、getter,在数据变动时发布消息给订阅者,触发 相应的监听回调

10 get 和 post区别

get:

1.从服务器获取数据,支持携带数据大小通常在2k内

2.参数全显示在url中,不安全

3.一般用于查数据

post:

1.向服务器发送请求数据,支持的数据大小可设定

2.url中只有资源路径,相对安全,涉及用户隐私的东西通常都用post传输

3.通常用于修改文件,传送文件

11 哪些细节可以优化前端开发的性能问题?

1 尽可能减少HTTP请求次数

2 压缩 CSS, JS,HTML 和 文件

3 使用轻量级框架

4 少用全局变量

5 尽量避免写在HTML标签中写Style属性

6 尽量使用css3动画,开启硬件加速

7 使用CDN加速(Content Delivery Network)

9 避免重定向

10 缓存AJAX

11 使用精灵图

12 减少 DNS 查询(减少 域名解析服务器/域名解析 查询)

13 避免使用table布局,尽量使用css+div布局,原因也要了解一下

14 减少dom 操作

12 http和https的区别?

1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。

2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议 。

3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

4、https是以安全为目标的http通道。http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全,简单说就是 http 的安全版

13 json字符串和js对象如何互相转换?

JSON.stringfy() 将一个 js值(对象或者数组) 转换为一个 JSON字符串 -> js对象数组转换成json字符串

JSON.parse() 使用ajax从服务器请求到的json字符串后解析为js对象 -> json字符串转换成js对象

14 h5新标签:

    <header> <nav> <section> <aside> <footer>
    <figure> <mark> <output> <source> <time> <video>
    <datalist>

15 H5新特性:

1 data-* (私有定义属性)

2 video/radio 视频/音频

3 canvas 绘制图像

4 geolocation 定位

5 WebSocket 新通信协议:前后端双向通信

该协议不实行同源策略,只要服务器支持,就实现了服务器和浏览器的全双向通信。

6 localStorage/sessionStorage 代替cookie本地存储

7 文件拖拽---将本地文件拖拽到网页中显示

8 Web Worker js本身是单线程,web worker是运行在后台的js,不会影响主线程的运行,为js创造多线程环境,提高性能

9.manifest 离线时对web应用进行缓存 应用缓存(appcache)/浏览器缓存

16 var let和cost区别

var:声明变量,变量可以更改,而且函数作用域内有效

let:声明变量,作用和var一样,只在let命令所在的代码块内有效

const:一旦声明,值就不能改变 相当于一个常量,更改的话会报错

17 不改变原数组的方法

1 join 数组转换 (数组 => 字符串), array.join(分隔符) 返回新数组

2 concat() 数组1.concat(数组2) 拼接

3 arr.slice(start,end) arr.slice(start) arr.slice();

4 map,filter,forEach,some,every等不改变原数组

18 c3如何实现一个元素 垂直居中 旋转

// 其实有看到有兄弟写了 十几种实现方式哈,后续补充
// 1.c3实现一个元素水平垂直居中:
display: flex; 
justify-content: center;(控制主轴方向对齐方式)
align-items: center;(控制侧轴方向对齐方式)

// 2.c3实现一个元素旋转:
transform: rotateZ(45deg);

// 3.实现盒子垂直居中:
方法1:定位
position:absolute;
top:50%
left:50%
margin-top: -100px;(盒子高度的一半长度)
margin-left: -100px;(盒子宽度的一半长度)

方法2:(此方法没检验。。。。)
margin-top:外盒子的一半高度px;
transform:translate:(50%0);

方法 3flex布局
display: flex; 
align-items: center;(控制侧轴方向对齐方式)
justify-content: center;

19 浮动原因,和清除浮动

浮动:盒子脱离标准流,给盒子加一个左浮右浮(float:left)会导致盒子浮动

浮动好处:
  1.块级元素可以1排显示
  2.行内元素可以设置宽度和高度
  3.元素没有设置宽度和高度时,宽度为内容撑开宽
  4.支持margin padding
  5.脱离标准流
清除浮动:
  1 父级overflow:hidden;
  2 给末尾加个空div标签:  clear:both
  3 父级给高度

20 css库 less(koala) sass

sass less 都是css的预处理器,是一种特殊的语言编译成css

优点:

1 结构清晰易于扩展

2 能屏蔽浏览器私有语法差异

3 轻松实现多重继承

4 完全兼容css代码

21 元素的display属性:

css规范规定,每个元素都有display属性,确定类型就能确定display值

    行内元素:a b span img input select strong
    块级元素:div ul ol li dl dt dd h1 ..p
    空元素(void):
    知名:br hr img input link meta
    鲜为人知:area base source embed
    样式转换:
    display:block           ->块级元素
    display:inline          ->行内元素
    display:inline-block    ->行内块元素

22 axios的优点?为啥axios是请求两次请求

  axios的优点:
      1.可以设置拦截请求和响应
      2.自动转换json请求和响应
      3.支持promise的api

  axios是请求两次请求的原因:
  Vue项目中使用axios组件,会发现在页面交互中发现axios会发送两次请求,
  一种请求方式为OPTIONS,另外一种为自己设置的。
  跨域资源共享标准新增了一组 HTTP 首部字段,
  允许服务器声明哪些源站有权限访问哪些资源。
  另外,规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法
  (特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),
  浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),
  从而获知服务端是否允许该跨域请求。
  服务器确认允许之后,才发起实际的 HTTP 请求。
  在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证
  (包括 Cookies 和 HTTP 认证相关数据)。 
  也就是说,它会先使用options去测试,你这个接口是否能够正常通讯,
  如果不能就不会发送真正的请求过来,如果测试通讯正常,则开始正常请求。 
  
  如果想解决这个问题呢,需要在后台进行设置,允许options请求,
  不然你的请求就会受到影响,后台并作出判断,
  如果请求方式为options,告诉它可以通讯,其他直接什么都不做。 
  
  
以下是PHP做设置内容 
    header("Access-Control-Allow-Origin:*"); 
    header("Access-Control-Allow-Headers:content-type"); 
    header("Access-Control-Request-Method:GET,POST"); 
    if(strtoupper($_SERVER['REQUEST_METHOD'])== 'OPTIONS'){ 
        exit; 
    } 

23 foreach 和 map区别

作用:都能通过遍历重组出自己想要的数组或者拿到自己要的数据

forEach 和 map 的区别:

forEach() :没有返回值,只是遍历数组中的每一项,不对原来数组进行修改,但是可以自己通过数组的索引来 修改原来的数组

map():有返回值,可以return出来 map返回一个新的数组 return的是啥,相当于把数组中的这一项变为啥,并不影响原来的数组,只是相当于把原数组克隆了一份,把克隆这一份的数组中的对应项改变了

24 创建对象的几种方式

1 通过 字面量 var obj = {...}

3 工厂函数: function 函数名(参数){...}

2 通过 系统构造函数 方式创建:var obj = new Object();

4 自定义构造函数 function 函数名(){...this.xx...}

25 什么是BFC?

BFC 直译为"块级格式化上下文",
规定了内部盒子如何布局,它是一个独立的渲染区域
容器里的子元素不会影响到外面的元素,外面的也不会影响到里面


会生成BFC的元素: 
根元素 
float属性不为none 
position为absolute或者fixed

26 css的引入方式有哪些?

内联,内嵌,外联,导入

27 link 和@import的区别:

link:
1.不存在兼容性问题,支持使用js改变样式
2.不仅可以加载 CSS 文件,还可以定义 RSS、rel 连接属性
3.加载页面时,link标签引入的 CSS 被同时加载

@import:
1.css2.1以下的浏览器不支持,不支持使用js改变样式,存在一个兼容性的问题
2.只有导入样式表的作用;
3.@import引入的 CSS 将在页面加载完毕后被加载。相当于会慢半拍

28 xml和json的区别?为什么现在都有json了,有的老公司还要用xml?

xml:扩展标记语言,是一种允许用户对自己的标记语言进行定义的源语言
  1 优点:
    格式统一,数据共享方便
  2 缺点:
    1 文件庞大,格式复杂
    2 代码不易维护
    3 不同浏览器之间解析XML的方式不一致,需要重复编写很多代码

json:轻量级的数据交换格式,具有良好的可读和便于快速编写的特性。
      JSON采用兼容性很高的、完全独立于语言文本格式
  优点:
   1 数据格式简单易于读写,便于快速编写
   2 占用宽带小(格式是压缩的)
   3 便于服务端解析(支持多种语言)能直接为服务器端代码使用,简化代码量,易于维护

  缺点:没有XML的通用性高,推广度还没有那么普及

29 cdn是什么?

全称是(Content Delivery Network)内容分发网络,其目的是让用户能够更快速的得到请求的数据。

简单来讲,cdn就是用来加速的,他能让用户就近访问数据,这样用户就能就更快的获取到需要的数据。

CDN的优势很明显:

(1)CDN节点解决了跨运营商和跨地域访问的问题,大大降低访问的延时;
(2)大部分请求在CDN边缘节点完成,CDN起到了分流作用,减轻了源站的负载。

30 什么是内存泄漏?哪些操作会造成内存泄露?如何解决?

内存泄漏:不再用到的内存,没有得到及时释放就叫做内存泄漏(对象不再被应用程序使用,但是垃圾回收器却不能移除它们,因为它们正在被引用。)

哪些会造成内存泄漏:
(1)意外的全局变量引起的内存泄露
(2)闭包。闭包可以维持函数内局部变量,使其得不到释放。
 解决之道,将事件处理函数定义在外部,解除闭包,或者在定义事件处理函数的外部函数中,删除对dom的引用。
(3)被遗忘的定时器
(4)dom元素被删除,其绑定的事件没有被移除

如何解决内存泄漏? 对于不再需要使用的对象,显示的将其赋值为null或者删掉

31 常见的布局方案有哪些?

静态布局,弹性布局,自适应布局,流式布局,响应式布局

(1)静态布局(Static Layout)
即传统Web设计,就是不管浏览器尺寸具体是多少,网页布局就按照当时写代码的布局来布置;
对于移动设备,单独设计一个布局,
在屏幕宽高有调整时,使用横向和竖向的滚动条来查阅被遮掩部分; 

(2)弹性布局 display:flex
弹性布局是CSS3引入的强大的布局方式,用来替代以前Web开发人员使用的一些复杂而易错hacks方法
(如使用float进行类似流式布局)。

(3)自适应布局(Adaptive Layout) (元素位置会根据尺寸改变,但是元素大小变)
自适应布局(Adaptive):分别为不同的屏幕分辨率定义布局。
布局切换时页面元素位置发生改变,页面元素不随窗口大小的调整发生变化。

(4)流式布局 (会根据屏幕大小调整元素的宽高,但是不会改变元素的位置)
流式布局(Liquid)的特点(也叫”Fluid”) 是页面元素的宽度按照屏幕进行适配调整

(5)响应式布局(Responsive Layout)(自适应和流式布局 的合体,同时位置会变而且大小也会变)
可以把响应式布局看作是  流式布局  和  自适应布局  设计理念的融合。 每个屏幕分辨率下面会有一个布局样式,
同时位置会变而且大小也会变。

32 jq 中 attr和prop区别?

prop:对于HTML元素本身就带有的固有属性,在处理时,使用prop方法。固有属性
attr:对于HTML元素我们自己自定义的DOM属性,在处理时,使用attr方法。

33 vue生命周期 (8个阶段)

vue实例从创建到销毁的过程,就是生命周期。
也就是从   开始创建、初始化数据  ->   
           编译模板、挂载DOM     ->  
           渲染、更新  ->  
           渲染、卸载
           等一系列过程,我们称这是vue的生命周期

创建前/后:
在beforeCreate阶段,vue实例挂载元素el和数据对象data都为undefined,还未初始化。
在create阶段,vue实例的数据对象data有了,el还没有

载入前/后:
在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的DOM节点,
data.message还未替换。
在mounted阶段,vue实例挂载完成,data.message成功渲染
更新前/后:
当data变化时,会触发beforeUpdate和updated方法
销毁前/后:
beforeDestroy
destroyed
在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和DOM的绑定,但是DOM结构依然存在

vue生命周期的作用是什么?
它的生命周期有多个事件钩子,让我们能在它的不同阶段操作它的数据从而达到我们的目的
也就是,在控制整个vue实例的过程时有生命周期能更容易形成好的逻辑

34 组件之间的传值?

1.父组件 -> 子组件
在父组件给子组件绑定属性,子组件通过:props属性来接收传递的数据

2.子组件 -> 父组件
方式:在父组件中声明一个接收数据的函数,父组件给子组件绑定事件,子组件通过$emit触发事件,
并且可在此时传递参数,父组件通过定义好的监听事件接收参数

3.兄弟组件
创建一个新的vue实例,让各个兄弟组件共用一个事件机制,
通过事件触发$emit(方法名,传递的数据),
在mounted()钩子函数中, 触发事件$on(方法名,callback(接收数据))
此时callback函数中的this已经发生了改变,可以使用箭头函数

35 http三次握手?

TCP在传输之前会进行三次沟通,一般称为“三次握手”

传完数据断开的时候要进行四次沟通,一般称为“四次挥手”

第一次与第二次握手完成意味着:A能发送请求到B,并且B能解析A的请求
第二次与第三次握手完成意味着:A能解析B的请求,并且B能发送 请求到A

好处:
   这样就保证了AB之间能互相发送请求也能互相接收解析请求
   同时  避免了因为   网络延迟   产生的     重复连接问题
   有三次握手的话,B返回的建立请求A就不会理睬了 

36 ES6是什么?

ES6是JavaScript语言的下一代标准. 简单来说,ECMAScript是JavaScript语言的国际标准,JavaScript是ECMAScript的实现. ES6的目标,是使得JavaScript语言可以用来编写大型的复杂的应用程序,成为企业级开发语言.

37 原型链图

截图

38 promise , await async

ES6中,提供了一个构造函数 Promise,这个构造函数其实就是书写异步代码的一种方式,
它能够解决回调函数嵌套的问题, 在promise的内部会封装一个异步的任务
promise对象的方法
    then(): 处理成功的结果 
    catch():处理失败的结果  ==>   then和catch不会同时触发
    resolve,
    
如果promise对象reject了,promise会抛出异常

axios() 返回的就是promise,promise解决回调嵌套问题 

asyncawait 是编写异步代码的终极解决方案,解决回调地狱的终极方法
async用于修饰一个函数,async就是异步的意思, 异步函数也就意味着该函数的执行不会阻塞后面代码的执行

await: 等待一个promise成功的结果, 在等待结果之前阻止async函数的执行,
await一定要在async函数中使用  async function(){ await .... }

1. await必须使用在async修饰的函数中
2. await后面会跟一个promise对象
3. await会暂停async函数的执行,直到等到了promise的成功结果,才会执行await以外async以内的代码

// try .. catch

39 如何清理应用缓存和浏览器缓存?

manifest:应用缓存是html5的重要特性之一,提供了离线的功能,
让程序可以获取本地网站内容(html,css,图片,js),这个功能可以提高网站功能,
他不强制用户访问的网站内容被缓存

浏览器缓存:浏览器的设置里就有这个功能,可以点击清除

40 解构

简单来说就是按照一定的匹配模式从数组和对象中提取我们所需要的变量
从一个对象一次性解析出多个属性给不同变量
const { text,list } = this.data

解构赋值语法  是一个 Javascript 表达式,这使得可以将值从数组或属性从对象提取到不同的变量中。
等号右边的结构必须是可遍历的结构,不然会报错,模式不同的变量是undefined
使用场景:1 ajax后台请求回来的数据 2 交换变量赋值更方便

41 vuex

Vuex 是一个专为 Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态, 并以相应的规则保证状态以一种可预测的方式发生变化。Vuex是用来管理组件之间通信的一个插件

vuex是为了管理页面的共享数据
state: 存变量,组件的状态.组件之间的数据存储
mutation: 提供方法
页面通过 this.$store.commit('函数名', 值) 来改变state中的变量值
this.$store.state 变量名获取state中的值

42 过滤器filter

过滤器不改变真正的data,而只是改变渲染的结果,并返回过滤后的版本。有点像一个可复用的方法~

43 项目开发流程 (大致流程)

1-需求设计
    做这个项目目的: 盈利
       小视频  商机  想法 
       公司leader  产品经理

2-原型设计
    画原型图 --> 给产品打草稿 
    负责人: 产品经理 

3-UI设计
    去美化原型图, 切图 
    负责人: UI设计师 

4-技术选型
    用什么技术做这个项目做合适:
    前端技术选型:html  html5 css2  css3  jquery  vue.js......
    后台技术选型:java  php  python ....
    数据库技术选型: mysql sqlServer ...

    考虑因素: 开发成本 , 团队的技术水平; 服务

    负责人: 项目经理 技术总监 


5-数据库设计
    前端 后台  数据库 
    将数据库表设计好
    负责人: DBA   后台

6-项目架构设计
    在开发之前,要规范文件和代码 各种格式命名
    1-组织文件结构
    2-组织代码的规范和命名

7-迭代开发(循环)
    开发
    测试
    开发
    测试
    开发
    测试
    没有bug为止 
    。。。
    项目需求变了...
    
8-集中测试
    有bug 回到7
    无bug 到9 
    公测:游戏 
    内测:

9-部署上线:
 将项目有公司内网  移动 公共互联网上;

44 Bom的基本对象和Dom基本对象

Bom的基本对象(浏览器对象模型):window (setTimeout(),clearInterval(),alert()等等等) 
location  history  screem  navigator frame
常用的API:
  location----当前访问的url地址对象
  location.href------设置新的url地址会在当前窗口打开新的url
  location.reload()---刷新当前页面
  location.search()----获取url的参数
  history----历史记录栈


Dom的基本对象(文档对象模型):在前端开发时,我们往往需要在页面某个地方添加一个元素或者删除元素,
这种添加元素、删除元素、替换元素等的操作就是通过DOM来实现的,也就是我们平时所说的dom节点
常用的API:  节点查找 节点创造 节点修改 元素属性型

  
以下作者介绍的更更细 https://blog.csdn.net/qq_37674616/article/details/82584566

image.png

45 H5中解决了ajax不能后退的问题:

history.pushState
history.replaceState

46 原生获取属性:

setAttribute() 添加指定的属性并为其赋值指定的值

getAttribute() 返回指定的属性名的属性值

47 typeof null : "object"

48 事件流的三个阶段:

1 捕获(从上往下)
  事件从文档的根节点流向目标对象节点。途中经过各个层次的DOM节点,
  并在各节点上触发捕获事件,直到到达事件的目标节点。
  捕获阶段的主要任务是建立传播路径,在冒泡阶段,事件会通过这个路径回溯到文档跟节点。

2 事件目标
  当事件到达目标节点的时候,事件就进入了目标阶段。事件在目标节点上被触发,
  然后会逆向回流,直到传播至最外层的文档节点
  
3 冒泡(从下往上)
  事件在目标元素上触发后,并不在这个元素上终止,会沿着捕获阶段的路线原路返回。
  它会随着DOM树一层层向上冒泡,回溯到根节点。
  冒泡过程将我们从对特定元素的事件监听中释放出来,
  如果没有事件冒泡,我们需要监听很多不同的元素来确保捕获到想要的事件。
  
  事件委托---还要再深入学习一下

image.png

三大家族:offset(获取元素位置和大小) scroll(滚动) client(可视区,内容+padding)

49 继续提高自己的代码:

1 易维护
2 可测试
3 高性能
4 低流量(移动端)

50 svn 管理

51 jQuery的事件委托方法:

事件委托:就是利用冒泡的原理,把事件加到父元素或祖先元素上,触发执行效果。
优点:提高JavaScript性能。事件委托可以显著的提高事件的处理速度,减少内存的占用。

jQuery的事件委托方法: on   live   delegate   bind 

1.bind(type,[data],fn) 为所有匹配元素的特定事件绑定事件处理函数,
只能将事件绑定在已经存在的元素上,不能给未来新增的元素绑定事件,存在局限性。

例子:$("a").bind("click",function(){alert("ok");}) ==> 为a标签的click事件绑定事件

2.live(type,[data],fn) 给所有匹配的元素附加一个事件处理函数,即使这个元素是以后再添加进来的
通过冒泡的方式来绑定到元素上的,更适合列表类型,和.bind()相比它的优势是支持动态数据。

3.delegate(selector,[type],[data],fn) 指定的元素添加一个或多个事件处理程序,
并规定当这些事件发生时运行规定的函数,更精确的小范围使用事件代理,
可指定事件委托对象,直接锁定指定选择器,性能优于.live()

4.on(events,[selector],[data],fn) 在选择元素上绑定一个或多个事件的事件处理函数,
事件委托对象选填,如果不填,即给对象自身注册事件,填了作用和delegate一致。

委托事件写法:
$(父元素).on('click','子元素选择器',function(){
        //代码块
 });


on是对另外三种方式的整合,是一种新的事件绑定机制,其他三种已经废弃

52 http请求类型分哪几种

get  post  delete  put  options(预检)

53 后端对options处理

前端在跨域的时候,会在请求的header放入一些请求信息,发送一条预检给服务器,这个时候的请求类型是options,服务端路由应该对 OPTIONS 类型请求做出响应,这样才不会报错,若服务器没配置会报404

54 xss攻击

概念:
全称为 跨站脚本攻击
XSS攻击是Web攻击中最常见的攻击方法之一,它是通过对网页注入可执行代码且成功地被浏览器执行,
达到攻击的目的,形成了一次有效XSS攻击,一旦攻击成功,它会带来巨大的危害,是web安全的头号大敌。

实施XSS攻击需要具备两个条件:
  一、需要向web页面注入恶意代码;
  二、这些恶意代码能够被浏览器成功的执行。

解决方法:
1 在表单提交或者url参数传递前,对需要的参数进行过滤
2 过滤用户输入的 检查用户输入的内容中是否有非法内容

例如:
在一个论坛发帖中发布一段恶意的JavaScript代码就是脚本注入,
如果这个代码内容有请求外部服务器,那么就叫做XSS攻击了。

55 浅拷贝 和 深拷贝 ? 为什么object是复杂数据类型?

基本数据类型:名值存储在栈内存中; Boolean、Null、Undefined、Number、String、Symbol

引用数据类型:名存在 栈内存 中,值存在于 堆内存 中,但 栈内存 会提供一个 引用的地址 指向 堆内存中的值。 Object、Array、Function、RegExp、Date等,

深拷贝与浅拷贝的概念只存在于引用数据类型

什么时候使用深拷贝?

我们在希望改变新的数组(对象)的时候,不改变原数组(对象)

浅拷贝: 浅拷贝将原对象或原数组的引用直接赋给新对象,新数组,新对象/数组只是原对象的一个引用
(拷贝后的引用都是指向同一个对象的实例,彼此之间的操作会互相影响)
====>
  方式1 ES6 扩展运算符 ... 
  var obj = { a:1, arr: [1,2] };
  let newObj = {...obj};
  
  方式2 ES6 Object.assign() // 多层是浅拷贝 一层是深拷贝
  
  方式3  jQuery.extend()
  var obj = { a:1, arr: [1,2] };
  let newObj = jQuery.extend({}, obj);
  obj.arr[0] = 10;
  console.log(newObj.arr[0]); // 10

深拷贝就是增加一个指针,并且申请一个新的内存地址,使这个增加的指针指向这个新的内存, 然后将原变量对应内存地址里的值逐个复制过去(注意拷贝的是“值”而不是“引用”)

  ===>深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象
      方法一: 用 JSON.stringify 把对象转换成字符串,再用 JSON.parse 把字符串转换成新的对象。可以转成 JSON 格式的对象才能使用这种方法
  JSON.parse(JSON.stringify(obj)):可实现多维对象的深拷贝,但会忽略undefined、任意的函数、symbol 值
  方法二: Array====> array.slice(),array.concat(), 
  方法三: ... 操作符:只能实现一维数组的深拷贝,
  方法四: Object.assign():只能实现一维对象的深拷贝 

  深拷贝函数改进(防止循环递归):
  function deepClone(obj, parent = null){ // 改进(1)
  let result = Array.isArray(obj)?[]:{};
  let _parent = parent;  // 改进(2)
  while(_parent){ // 改进(3)
    if(_parent.originalParent === obj){
    return _parent.currentParent;
 }
    _parent = _parent.parent;
  }
  if(obj && typeof obj === "object"){
    for(let key in obj){
      if(obj.hasOwnProperty(key)){
        if(obj[key] && typeof obj[key] === "object"){
          result[key] = deepClone(obj[key],{ // 改进(4)
            originalParent: obj,
            currentParent: result,
            parent: parent
          });
        }else{
          result[key] = obj[key];
        }
      }
    }
  }
  return result;
 }

  // 调试用
  var obj1 = {
    x: 1, 
    y: 2
  };
  obj1.z = obj1;
  var obj2 = deepClone(obj1);
  console.log(obj1); //太长了去浏览器试一下吧~ 
  console.log(obj2); //太长了去浏览器试一下吧
  
  

56 关于继承 你会哪些继承?

www.jianshu.com/p/2f5b7b29b…

   (1).原型链继承:
    function Parent () {
     this.name = '欣雨';
    }
    Parent.prototype.getName = function () {
     console.log(this.name);
    }
    function Child () {}
    Child.prototype = new Parent();
    var child1 = new Child();
    console.log(child1.getName()) // 欣雨

    但是原型链继承有两个问题:
    1.引用类型属性被所有实例共享->栈内存有两个值,而指针指向同一个堆内存,一个实例属性更改,另一个实例属性也更改(意思原型链继承只做了浅拷贝)
    2.在创建 Child 的实例时,不能向Parent动态传参

  (2).构造函数继承:
    function Parent (name) {
    this.names =  ["小米", "小明"];
        //this.getName = function () {
        //  console.log(this.name)
        //}
    }
    function Child (name) {
      Parent.call(this, name); // 重点
      // Parent.apply(this, arguments); // 第二种方法,更通用
    }
    var child1 = new Child();
     console.log(child1) // {names: ["小米", "小明"]}
    child1.names.push('小哥');
    console.log(child1.names); //  ["小米", "小明", "小哥"]
    var child2 = new Child();
    console.log(child2.names); //  ["小米", "小明"]

    call()或apply(),实际上是在新创建的Child实例的环境下调用了Parent构造函数,call()或apply()会把父类方法变成子类方法独有的属性。(也就是深拷贝)
    缺点:就是每次创建实例都会创建一遍方法。每次new Child()都会创建一次这个方法,但是这个方法是做同一件事情,就是拿到名字,岂不是很浪费内存

  (3). 组合继承(原型链继承+构造函数继承)
    function Parent (name) {
    this.name = name;
    this.colors = ['red', 'blue', 'green'];
    }
    Parent.prototype.getName = function () {
      console.log(this.name)
    }
    function Child (name, age) {
      Parent.call(this, name); 
      this.age = age;
    }
    Child.prototype = new Parent(); // 主要是这一步 之前每一次new实例重复创建问题。原理就是不在函数内,创建跟它没关呀
    var child1 = new Child('小鱼', '18');
    console.log(child1) // 实例本身和__proto__有相同的属性
    child1.colors.push('black');
    console.log(child1.name); // 小鱼
    console.log(child1.age); // 18
    console.log(child1.colors); // ["red", "blue", "green", "black"]
原来构造函数方式是不能继承原型属性/方法 (原型中定义的方法和属性对于子类是不可见的)--->原来还有特殊规定呀。\color{red}{原型链继承的方式就可以继承原型的属性/方法}。
    

57 React 的 diff 算法

58 sessionStorage内可以存字符串吗? 里面可以存数组和对象吗?

sessionStorage要看业务而定,一般存储的都是JSON,当然有些业务也会存单独字符串

59 你对webpack的理解和了解 的配置

webpack是一个打包模块化javascript的工具,在webpack里一切文件皆模块,通过loader转换文件,通过plugin注入钩子, 最后输出由多个模块组合成的文件,webpack专注构建模块化项目。

WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。

webpack执行 -> 取得webpack.config.js的配置和默认配置合并 -> 然后执行plugin

    先理解四个核心概念:

    1 入口(entry)  ->指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始
    2 输出(output) ->告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件
    const path = require('path');
    module.exports = {
      entry: './path/to/my/entry/file.js',
      output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'my-first-webpack.bundle.js'
      }
    };

   3 loader -> 可以将所有类型的文件转换为 webpack 能够处理的有效模块,
   然后你就可以利用 webpack 的打包能力,对它们进行处理。
   
   
  几个常见的loader:

file-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件
image-loader:加载并且压缩图片文件
babel-loader:把 ES6 转换成 ES5
css-loader:加载 CSS,支持模块化、压缩、文件导入等特性
style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS。
eslint-loader:通过 ESLint 检查 JavaScript 代码


  loader的两个目标:


test 属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。
use 属性,表示进行转换时,应该使用哪个 loader。

    const path = require('path');
    const config = {
      output: {
        filename: 'my-first-webpack.bundle.js'
      },
      module: {
        rules: [
          { test: /\.txt$/, use: 'raw-loader' }
        ]
      }
    };
  module.exports = config;

  4 插件(plugins) 插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量
    安装插件:npm install --save-dev webpack-manifest-plugin;
    在 webpack.config.js中引入,大致如下:
    var ManifestPlugin = require('webpack-manifest-plugin');
    module.exports = {
       plugins: [
         new ManifestPlugin() // ManifestPlugin方法可以接受一些选项参数options,如 new ManifestPlugin(options)
       ]
    };

  html-webpack-plugin 防止引用缓存的外部文件问题,为html文件中引入的外部资源,可以生成创建html入口文件
  mini-css-extract-plugin:分离css文件,对你的样式进行模块化拆分
  webpack-manifest-plugin: 能够在项目根目录生成一份## manifest.json的文件,
  通过该文件的映射关系可以让我们知道webpack是如何追踪所有模块并映射到输出bundle中的
  happypack:多线程编译,加快编译速度
  clean-webpack-plugin:在编译之前清理指定目录指定内容。

60 webpack优缺点:

  webpack有哪些优点

专注于处理模块化的项目,能做到开箱即用,一步到位
可通过plugin扩展,完整好用又不失灵活
使用场景不局限于web开发
社区庞大活跃,经常引入紧跟时代发展的新特性,能为大多数场景找到已有的开源扩展
良好的开发体验
  webpack的缺点
    webpack的缺点是只能用于采用模块化开发的项目

61 require和import的区别?

    node编程中最重要的思想就是模块化,importrequire都是被模块化所使用。
  webpack遵循的是node语法,而require是node语法
  require:
  (1) AMD规范引入方式,
  (2) 运行时调用,所以require理论上可以运用在代码的任何地方,
  (3) 是赋值过程,其实require的结果就是对象、数字、字符串、函数等,再把require的结果赋值给某个变量
  (4) 运行时加载
  (5) require / exports 只能在运行时确定模块的依赖关系及输入/输出的变量,无法进行静态优化

  import:
  (1) 是es6的一个语法标准,如果要兼容浏览器的话必须转化成es5的语法,
  (2) 是编译时调用,所以必须放在文件开头,
  (3) 是解构过程,但是目前所有的引擎都还没有实现import,
  (4) 编译时加载
  (5) import / export 支持编译时静态分析,便于JS引入宏和类型检验。动态绑定。

  我们在node中使用babel支持ES6,也仅仅是将ES6转码为ES5再执行,import语法会被转码为require

62 箭头函数和传统函数的区别?

箭头函数的特点:
  更简洁的语法
  没有this
  不能使用new 构造函数
  不绑定arguments,用rest参数...解决
  使用call()和apply()调用
  捕获其所在上下文的 this 值,作为自己的 this 值
  箭头函数没有原型属性
  不能简单返回对象字面量
  箭头函数不能当做Generator函数,不能使用yield关键字
  箭头函数不能换行

63 请求行有哪些

     http协议报文
    (1).请求报文(请求行/请求头/请求数据/空行)
        ~请求行
            请求方法字段、URL字段和HTTP协议版本
            例如:GET /index.html HTTP/1.1
                get方法将数据拼接在url后面,传递参数受限
            请求方法:
                GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT
        ~请求头(key value形式)
            User-Agent:产生请求的浏览器类型。
            Accept:客户端可识别的内容类型列表。
            Host:主机地址
        ~请求数据
            post方法中,会把数据以key value形式发送请求
        ~空行
            发送回车符和换行符,通知服务器以下不再有请求头
    (2).响应报文(状态行、消息报头、响应正文)
        状态行
        消息报头
        响应正文

67 this的指向问题

68 数组有哪些方法?

     数组的创建有两种方式 1使用Array构造函数 2 var创建数组
  数组的方法:
    1 join() 把数组中的所有元素放入一个字符串
    2 push()和pop() 
      push(): 可以接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度。
      pop():删除数组末尾最后一项,减少数组的 length 值,然后返回移除的项。
    3 shift() 和 unshift()
      shift():删除原数组第一项,并返回删除元素的值;如果数组为空则返回undefined 。
      unshift: 将参数添加到原数组开头,并返回数组的长度 。  
    4 sort()  按升序排列数组项——即最小的值位于最前面,最大的值排在最后面。
    5 reverse()  反转数组项的顺序。
    6 concat() 方法用于连接两个或多个数组。 该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本
    7 slice()  返回从原数组中指定开始下标到结束下标之间的项组成的新数组。可以接受一或两个参数,即要返回项的起始和结束位置(不包括结束位置的项)
    8 splice() 很强大的数组方法,它有很多种用法,可以实现删除、插入和替换。
      删除:可以删除任意数量的项,只需指定 2 个参数:要删除的第一项的位置和要删除的项数。例如, splice(0,2)会删除数组中的前两项。
      插入:可以向指定位置插入任意数量的项,只需提供 3 个参数:起始位置、 0(要删除的项数)和要插入的项。例如,splice(2,0,4,6)会从当前数组的位置 2 开始插入46。
      替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定 3 个参数:起始位置、要删除的项数和要插入的任意数量的项。
      插入的项数不必与删除的项数相等。例如,splice (2,1,4,6)会删除当前数组位置 2 的项,然后再从位置 2 开始插入46splice()方法始终都会返回一个数组,该数组中包含从原始数组中删除的项,如果没有删除任何项,则返回一个空数组。
    9 indexOf()和 lastIndexOf()  接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的开头/结尾(位置 0)开始向后查找。
    10 forEach()
    11 map() 内部返回一个值
    12 filter() 过滤”功能,数组中的每一项运行给定函数,返回满足过滤条件组成的数组。
    13 every() 判断数组中每一项都是否满足条件,只有所有项都满足条件,才会返回true
    14 some() 判断数组中是否存在满足条件的项,只要有一项满足条件,就会返回true。
    15 reduce()和 reduceRight()  

69 为什么尽量不使用table布局

70 React的性能优化

blog.csdn.net/weixin_4190…

    1 属性传递优化: 
  (1) 在React中,事件的声明方式有三种。
    a.事件在声明时一起绑定:<button onClick={this.onClick.bind(this)}></button>
    b.使用函数式声明事件:<button onClick={() => this.onClick()}></button>
    c.在按钮内声明,在constructor内绑定:
      constructor(props){
        super(props);
        this.onClick = this.onClick.bind(this)
      }
      render(){
        return (
          <button onClick={this.onClick}></button>
        )
      }
      ab相对于c,再次执行时都要再渲染一编render()里的bind函数和函数声明式,而c的绑定函数只执行一次,并不会每次执行时都进行调用
      三者对性能优化的优先级为c>b>a
  (2)切忌将props/state以展开形式传递给子组件,除非子组件需要用到父组件的所有props/state。 ----错误示范--> <div style={{ color:'green'}} name={{age:18}}></div>
   正确的用法应该是在render()内先将对象定义,再在组件中调用    --正确示范--> <div name={this.state.name}></div>
  2. 多组件优化:

71 bind:

69 Vue的性能优化

70 去重 逆向去重

71 vue和react 的route的区别

72 有个紧急上线 但你写的东西有部分没写完 这个时候你怎么处理

73 git

74 react从有到无的渲染机制

75 Rem布局

假设 html { font-size: 20px; },那么 1rem 就等于 20px。

76 垂直居中的方法 越多越好

77 代码题

一个是三秒后执行 settimeout 一个是0秒执行 还有一个是for循环 那么打印这三个中的东西 先出现哪个

    setTimeout(()=>{
      console.log(1);
    },1000);
    setTimeout(()=>{
      console.log(2);
    },0);
    for(i = 1;i <2; i++) {
      console.log(3);
    };
     3  undefined 2  1 

78 npm 原理

79 虚拟dom

    虚拟Dom是什么?
    原生的 JavaScript程序中,我们直接对 DOM进行创建和更改,而 DOM元素通过我们监听的事件和我们的应用程序进行通讯。
    React会先将你的代码转换成一个 JavaScript对象,然后这个 JavaScript对象再转换成真实 DOM。这个 JavaScript对象就是所谓的虚拟 DOM。
    当我们需要创建或更新元素时, React首先会让这个 VitrualDom对象进行创建和更改,然后再将 VitrualDom对象渲染成真实DOM。
    当我们需要对 DOM进行事件监听时,首先对 VitrualDom进行事件监听, VitrualDom会代理原生的 DOM事件从而做出响应。

    虚拟Dom比普通Dom更快吗?
    直接操作 DOM是非常耗费性能的。但是 React使用 VitrualDom也是无法避免操作 DOM的。VitrualDom不具有任何优势,甚至它要进行更多的计算,消耗更多的内存。
    VitrualDom的优势在于 React的 Diff算法和批处理策略, React在页面更新之前,提前计算好了如何进行更新和渲染 DOM,优化了性能

Redux 中间件

80 什么是盒子模型?

由元素内容,bordermarginpadding四部分组成盒子模型。

81 src和href的区别?

src是引入外部资源,比如,js,css。

href是建立和当前元素和跳转页面之间的链接,用于超链接。

82 怎样添加、移除、移动、复制、创建和查找节点?

    1)创建新节点
  createDocumentFragment() //创建一个DOM片段
  createElement() //创建一个具体的元素
  createTextNode() //创建一个文本节点

  2)添加、移除、替换、插入
  appendChild() //添加
  removeChild() //移除
  replaceChild() //替换
  insertBefore() //插入

  3)查找
  getElementsByTagName() //通过标签名称
  getElementsByName() //通过元素的Name属性的值
  getElementById() //通过元素Id,唯一性

83 数组去重

[...new Set([1,2,3,1,'a',1,'a'])]

84 冒泡和捕获

给一个dom同时绑定两个点击事件,一个用捕获,一个用冒泡,先执行冒泡还是捕获? 捕获先于冒泡。顶部捕获=>底部冒泡=>第二层捕获=>第二层冒泡。

85 函数节流和函数防抖

    防抖节流都是 让固定时间内限制请求次数
  你下拉加载, 有的用户会疯狂的 1秒下拉几万次.那你也只能请求一次

  函数节流:
          高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率
          实现方式:每次触发事件时,如果当前有等待执行的延时函数,则直接return

  函数防抖: 
          触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。
          实现方法: 每次触发事件时设置一个延迟调用方法,并且取消之前的延时调用方法
          缺点: 如果事件在规定的时间间隔内被不断的触发,则调用方法会被不断的延迟

86 输入url整个过程。

网络传输:输入网址 =>dns解析ip=>TCP三次握手=>发送http请求=>服务器重定向=>处理请求,返回http响应=>关闭TCP链接=>浏览器得到数据解析html布局渲染。

dom渲染:构建dom树(构建dom节点)=>构建渲染树(解析样式信息)=>布局渲染树(布局dom节点)=>绘制渲染树(绘制dom节点)。

87 CROS跨域资源共享

      简单请求:get, post
  服务端设置:Access-Control-Allow-Origin: "*"
  前端不需要。
  非简单请求:put,delete
  服务端设置:Access-Control-Allow-Origin: "*"; 还需要设置method和header
  前端需要设置header。

88 React的setState到底做了什么?

当你传一个普通的对象 this.setState( {num: this.state.num + 1} ) 时,他会进入队列

队列里就做一件事 Object.assign( this.state, stateChange ) ,this.state永远都是之前的0。

00次以后就通过 flush 方法清空队列,包裹flush的是 **Promise.resolve().then(flush) **,使用微异步跳出队列,渲染页面。

原来setState支持传函数,这样它内部通过递归方式获取前一个值,就可以做到累加,并且还只会渲染一次页面,多神奇。

89 浏览器缓存 分为强缓存和协商缓存

  协商缓存:Etag/If-None-Match

90 title与h1的区别,b与strong的区别,i与em的区别?

  首先要明白的是什么是物理元素,什么是逻辑元素?title,b,i是物理行为,
  比如b告诉浏览器我加粗了,而h1strongem是逻辑行为,通过语义化方式告诉浏览器我是重要的。

91 你是如何推动你们的框架的,你是如何给框架升级的?

  首先在架构项目前思考:
  ① 如何将一个复杂的页面拆分为一个个独立的页面组件模块
  ② 如何将分拆后的业务组件模块重新合为一个完整的页面
  ③ 从重构角度看组件化开发带来的好处
  ④ 从前端优化的角度看待组件化开发

92 es6新增:

  1. let const 
  2. 箭头函数
  3. find findIndex
  4. 字符串startsWith endsWith includes
  5. 对象的简写
      1. 对象的属性名和值名字相同的时候,可以省略一个
      2. 对象中的方法可以省略
        sayHi:function(){...}  === sayHi(){...}
  6. 函数参数的默认值  -->默认参数可以写在()里
  function add (n1 = 0, n2 = 0) {
          // 函数参数的默认值
          // n1 = n1 || 0
          // n2 = n2 || 0
          console.log(n1 + n2)
        }    
  7. 模板字符串
  在ES6中,允许使用 ``  反引号 来定义一个字符串 ``
  1. 允许换行
  2. 拼串中允许使用插值  ${}

93 var let const 区别

var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。

let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。

const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改。

94 vue全家桶之一-----vue.router 路由 (实现单页面)


     路由规则: 根据给的不同url 给你映射到 不同的页面中去
    一个指路的功能

    而 vue的router:
    根据不同的锚点值,给你映射到不同的组件去

    ue router的功能:构建 单页面应用程序
    页面只有一个,组件可以有很多个

    步骤:
     1,引包 : 引入   vue.js    vue-router.js
     2,定义一些组件 Vue.component 全局注册一个组件 组件名首字母一般大写 1个属性
                     Vue.components('music', {
                       template;`
                       <div> 这是一个组件 </div>
                       `
                     })
       ===> 
     const  Home = { template:`....`}
     3,创建一个 vueRouter对象-----路由对象  2个属性
                                 // 指定路由的规则  path:/home  Home
     const router = new VueRouter({routes:[{path:'路径',component:Home},{...},{...}]})
     4,把路由对象 和  vm实例绑定
     const vm = new Vue({el:'#app',router:router})
     const vm = new Vue({el:'#app',router})
     5,指定路由的出口,根据地址可以匹配搭配对应的组件,通过组件渲染的内容会替换出口
     <router-view></router-view>
     6,路由的入口 相当于a  用于点击更换不同的组件
     <router-link to="路径">XX</router-link>


Vue中this.$router.push(参数) 实现页面跳转:
  https://blog.csdn.net/qq_37548296/article/details/90446430
    我们在执行点击按钮跳转页面之前还会执行一系列方法,这时可以使用 this.$router.push(location) 来修改 url以及 传参,完成跳转。
    push 后面可以是对象,也可以是字符串,还可以是命名的路由
        // 字符串
        this.$router.push('/home/first')
        // 对象
        this.$router.push({ path: '/home/first' })
        // 命名的路由
        this.$router.push({ name: 'home', params: { userId: wise }})

页面 跳转 并 传递参数 的方法:
    1 params
      由于动态路由也是传递params的,所以在 this.$router.push() 方法中path不能和params一起使用,否则params将无效。
      需要用name来指定页面 及 通过路由配置的name属性访问
      patams传参 ,路径不能使用path 只能使用name,不然获取不到传的数据

      /* router.js 文件*/
        import Vue from "vue";
        import Router from "vue-router";
        import MediaSecond from "@/views/EnterprisePage/MediaMatrix/second"; //资讯列表

        Vue.use(Router);
        export default new Router({
          routes: [ /* 进行路由配置 */
             {
                 name: "MediaSecond",
                 path: "/MediaSecond",
                 component: MediaSecond
             },
           ]
        })

      /* 通过name获取页面,传递params:*/
          this.$router.push({ name: 'MediaSecond',params:{artistName:artistName,imgUrl:imgUrl,type:2} })

      /* 在目标页面通过this.$route.params获取参数:*/
          if (this.$route.params.type == 2) {
              this.type = apis.getAtistDetails;
          } else {
              this.type = apis.getMessageList;
          }

  2 query 传参
        this.$router.push({ name: 'DetailManagement', query: { auditID: row.id, type: '2' } });
        this.$router.push({ path: '/DetailManagement', query: { auditID: row.id, type: '2' } });


this.$router.go和this.$router.push以及this.$router.replace的区别:
    1this.$router.go(val)    这里val一般是 number类型  通常是前进或者后退几个层级,
        在history中增加一个历史记录, 如果为0,则代表刷新当前页;
    2this.$router.push(param)  这里的param一般是路径名,
        而且在history中增加一个历史记录,可返回,比如this.$router.push(“/home”) 
    3this.$router.replace(param)  这里的param一般是路径名,代表替换当前路由,
        无法通过history返回到上一个页面。

vue 路由传参 params 与 query两种方式的区别
    1、用法上的
      query可以用path以及name来引入,params只能用name来引入,
        接收参数都是类似的,分别是this.$route.query.name和this.$route.params.name。
    注意接收参数的时候,已经是$route而不是$router了哦!!
    2、展示上的
      query更加类似于我们ajax中get传参,在浏览器地址栏中显示参数
        params则类似于post,不在浏览器地址栏中显示参数
        

95 你用过哪些vue的组件?

96 hash 和 history

单页面和多页面的优点和缺点 他们的不同?

集中的状态处理 比如 redux 数据状态的管理

97登录页是如何实现的

98element.ui 的组件 你们用了哪些。。。。

如果让你改element.ui组件的功能 你怎么改 一个input 已经封装好了,这个时候我想改里面的样式或者值(长度啊类型啊) 可以查一下元素 去改里面的元素类型

99代码题

    for (let i = 1; i <= 3; i++) {
setTimeout(function() {
console.log(i)
}, 0)
}


var obj = {
num: 2,
getNum: function() {
this.num = 3
console.log(this.num)
}
}
var func = obj.getNum
obj.getNum()
func()


for (let i = 1; i <= 3; i++) {
setTimeout(function() {
console.log(i) // 1 2 3
}, 0)
}
for (var i = 1; i <= 3; i++) {
setTimeout(function() {
console.log(i) // 444
}, 0)
}

100小伙伴提到过的面试题

如果商品列表有很多很多,我从第99个商品点进了商品详情页,那么我点击回退,是回到最上面的商品还是回到第99条的商品呢 一般根据路由直接回到最上面的商品,并且双刷新页面的; 要是想返回的时候回到99列表,直接从浏览器的路由 history.go(-1),走浏览器的路由系统,不会发送任何请求的,以前在哪里就在哪里

就是在页面有点击搜索的时候用个变量存储搜索条件和table的currentpage 在页面跳转的时候 用 this.props.dispatch(setHistoryPramas({存查询条件 }) 页面跳转回来的时候在componentDidMount 里面从this.props.historyparams里面取出查询条件 存查询条件如何直接发送一个请求,而不是把之前的数据也都加载出来对么

他还问,如果我返回到了第99条,那么前99条就会都需要加载处理,那么加载的就会比较慢,影响性能,该怎么处理 99个列表 ,你一定 不能 把这些数据通过代码缓存;接口都是分页返回的 ,一次性一般条件是返回10条左右 一下子给你传 上百万个数据让你前端这边处理 怎么可能不分页呢,后台返回列表,不分页就卡死了呀,所以先说是分页还是下拉加载,我操作下拉加载也是要后台支持分页的, 其实也是分页,怎么可能一次性返回所有数据.不然 ,第一次返回100W条list, 页面会白屏的 一般就两种情况分页或者下拉加载,移动端一般是下拉加载,app上拉加载的话,和你分页一样的,只是pageNum +1 了,是上拉加载,下拉刷新,不刷新就好,不刷新 你那些个dom都是加载完成的 你拉倒10000页也是只刷新加载的10条,之前拉的都是刷新完成的,都是加载完成的,不影响.

我估计是再问你react的 element diff 还有就是防抖 一般scrollView 第三方都帮我们处理好了;对,听起来很牛逼,其实就是一个flag开关,我们只要处理返回的数据,拼接就可以了

你上拉加载每次返回的数据都要拼接到原数据上,再加上唯一key,diff会判断出你哪些数据变了 然后在shouldComponentUpdate里判断一下,哪里数据变化了,哪里数据没有变化,这样的判断会让diff的数据减少很多, 比如你加载到了100页,你在shouldComponentUpdate判断了,diff就不会去重新diff前99页的内容 shouldComponentUpdate 我记得是决定你要不要再render 如果返回false 压根就不会再render了吧..是的 问diff的就比较难回答了,react15和react16不一样了 vue 其实也有类似的更新数据时的高效渲染 我们也学过 叫 就地复用

但是 并不是提高了性能 react的diff我看了大神解释 没有提高任何性能 diff递归遍历差异变化 超过16ms就会影响性能了 长时间占据浏览器的主线程去做js
所以呀 react又花了两年重构了diff 加入了react fiber

diff 其实就是枚举法 但它遵守几个规则 减少了时间和空间复杂度 比如 如果父节点不一样 那就不比较子节点了 直接重新渲染父节点--> 你说的那是以前的diff

以前,那个延迟等到for循环执行结束之后再执行的是不是不是setTimeout 队列执行完毕后再执行 先将它放到事件队列里面,等主程序执行完毕,再调用

101代码题

for (let i = 1; i <= 3; i++) { setTimeout(function() { console.log(i) // 1 2 3 }, 0) } for (var i = 1; i <= 3; i++) { setTimeout(function() { console.log(i) // 444 }, 0) } ---> 用var就是4 var会等循环走完 是不是因为let是在块级作用域内,里面的setTimeout也在这个作用域内呀 会执行完成之后才i++?

也可以理解为数组的方法,字符串的方法之类的-->内置对象

102如何解决SPA页面首屏加载速度慢的问题 用webpack插件就完事了

 1、抽取css文件 2、模块化抽取 3、gzip代码压缩 4、代码压缩 nginx开启gzip、sendfile
https://www.cnblogs.com/vipzhou/p/9114090.html
用webpack插件就完事了。我知道这个 
用commonschunkPlugin将某些文件提取出来其他在首页没有用到的依赖通过require.ensure()按需加载。
我这 ios app 就因为首页白屏1s被苹果拒绝了
验证现在各大UI框架都有内置的配就完了
我们是直接写个静态假的
不会优化, 首页是node建站自动生成了 
首屏加载 一般就是按需加载 图片啥的懒加载 
我就记着网上的一些方法,按需加载,9宫格布局,懒加载之类的
啥子 静态站?
就是一个假的 
那玩意 现在用nuxt或者next自动生成
里面配了一些商品链接 ,你也可以点
然后 等真的首页返回了再替换掉假的
vue的nuxt 和 react的next都支持生成静态站
很多 首页都是服务器渲染的  快
强交互还是SPA好点
其他的还是客户端
服务器渲染的首页  也是前端负责把页面弄上去吧   对 
嗯 其实就是搞个node中间层
我们写的假的首页 就是写一个手机屏幕的内容,超出屏幕的都不管了
差不多1秒 真的首页就返回了
其实SPA可以 在挂载点画个SVG 数据回来在隐藏掉也算提高用户体验 对,
挂载点 是挂载在dom元素上的事件属性的意思吗..  ->>不是 挂载点就是那个在html里的那个div id=app
所有组件啥的 最后不都是挂载他下面的咩
就VUE指定的那个EL  SVG只是个等待图 点击貌似也可以
SVG是可以交互和动态的,可以在SVG文件中嵌入动画元素还可以通过脚本来写动画

    狗倩倩总结 
如何解决SPA首屏加载速度慢
路由的懒加载:懒加载也叫延迟加载,即在需要的时候进行加载,随用随载。 在单页应用中,如果没有应用懒加载,
运用webpack打包后的文件将会异常的大,造成进入首页时,需要加载的内容过多,延时过长,不利于用户体验,
而运用懒加载则可以将页面进行划分,需要的时候加载页面,可以有效的分担首页所承担的加载压力,减少首页加载用时
1.路由懒加载:
vue-router配置路由 , 使用vue的异步组件技术 , 可以实现按需加载 .
export default new Router({
routes:[
{
path: '/my',
name: 'my',
//懒加载
component: resolve => require(['../page/my/my.vue'], resolve),
},
]
})

103垃圾回收机制

js 的一般是标记清除法
确定回收对象有两个算法:  引用计数法 可达性分析法
就是被人诟病的脏数据检查
在运行过程中都会创建许多对象,继而需要为这些对象分配内存地址,当这些对象不需要使用的时候,
需要释放其占用的内存地址,以供新的对象使用。关于对象内存释放的这一机制就叫做垃圾回收机制(GC)。

104validate 表单验证

  前端实现表单验证的方法之一  基于validate.js的表单验证方法。
1.下载和引入validate.js
2.建立表单
3.使用validate.js实现表单数据的验证
$(function(){
$("form").validate({
    rules: {
        userName: {
            required: true, //该项表示该字段为必填项
            maxlength: 5 //表示该字段的最大长度为5
        },
        passWord: {
            required: true,
            number: true  //表示该字段必须为数字
        }
    },
    messages: {
        userName: {
            required: "*必填",
            maxlength: "*最多5个字符"
        },
        passWord: {
            required: "*必填",
            number: "*必须是合法的数字"
        }
    }                    
})   
   });



 SPA页面首屏加载速度慢造成的白屏问题 其实和 路由懒加载是一个问题?
  先要模块化划分 需要做webpack中配置的  然后再进行按需求加载

105让你做一个登录页 你要考虑什么

表单验证  +  登录保持(token) + 还有与接口对接 看业务需求登录成功或什么 跳转到哪 
加上权限(导航守卫)的话要做路由控制吧 还有最好存一下用户信息 以后可能用



普通登录还算简单,可是你说权限 就会问你项目权限做到什么程度,是页面权限还是按钮权限,不一样呀,
页面权限是不同角色看到页面不一样,一般都是处理侧边栏菜单,按钮权限是 两个等级不同的角色都可以看到同一个页面,只是 一个具有操作权,一个没有
就像 系统管理员可以删除 人员信息,他手下的业务员只能看到列表,无法删除信息,
嗯对 权限大体分为两个维度,一个是路由 一个是页面 路由一般就是菜单 导航啥的 页面就包括接口权限 和 操作权限

panjiachen.github.io/vue-element… 配合手摸手一起看

106redux

my.oschina.net/kimyeongnam…

  1 什么是redux?
  js应用的 一种可预测的状态容器
  2 为什么使用redux?
  没有使用Redux的情况,如果两个组件(非父子关系)之间需要通信的话,可能需要多个中间组件为他们进行消息传递,这样既浪费了资源,代码也会比较复杂。
  Redux中提出了单一数据源Store 用来存储状态数据,所有的组建都可以通过Action修改Store,也可以从Store中获取最新状态。使用了redux就可以完美解决组建之间的通信问题。
  3 怎么使用Redux
(1) redux安装
  npm install --save redux
  npm install --save react-redux
  npm install --save-dev redux-devtools
(2) 创建store 用于存储state数据
import { createStore } from 'redux'
import reducer from './reducer';
const store = createStore(reducer);

export default store;
reducer:根据传入的action 向store返回新的state,可以接受state但是不能修改state,需要对state进行深拷贝

107react 15 生命周期

初始化阶段:
constructor 构造函数
getDefaultProps props默认值
getInitialState state默认值

挂载阶段:
componentWillMount 组件初始化渲染前调用
render 组件渲染
componentDidMount组件挂载到 DOM后调用

更新阶段:
componentWillReceiveProps 组件将要接收新 props前调用
shouldComponentUpdate 组件是否需要更新

componentWillUpdate 组件更新前调用
render 组件渲染
componentDidUpdate 组件更新后调用

卸载阶段:
componentWillUnmount 组件卸载前调用

108原型和原型链

    与大部分面向对象语言不同,ES6之前中并没有引入类(class)的概念,JavaScript并非通过类而是直接通过构造函数来创建实例。
  构造函数模式的目的就是为了创建一个自定义类,并且创建这个类的实例。构造函数模式中拥有了类和实例的概念,并且实例和实例之间是相互独立的,即实例识别。
  创建方式和普通函数没有区别,不同的是构造函数习惯上首字母大写,需要使用new关键字来调用。
  每创建一个构造函数,在构造函数中,为每一个对象都添加了一个一样方法,构造函数执行一次就会创建一个新的方法.
  为什么不把这个方法单独放到一个地方,并让所有的实例都可以访问到呢?这就需要原型
  
  那么原型是什么呢?
  在JavaScript中,每当定义一个函数数据类型(普通函数、类)时候,都会天生自带一个prototype属性,这个属性指向函数的原型对象,并且这个属性是一个对象数据类型的值。
  原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中共有的内容,统一设置到原型对象中。

  原型链呢?
  对象之间的继承关系,在JavaScript中是通过prototype对象指向父类对象,直到指向Object对象为止,这样就形成了一个原型指向的链条,专业术语称之为原型链。
  普通人继承人类,人类继承对象类: person → PersonObject


  当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如果找到则直接使用。
  如果没有则去原型的原型中寻找,直到找到Object对象的原型,Object对象的原型没有原型,如果在Object原型中依然没有找到,则返回undefined

  使用对象的hasOwnProperty()来检查对象自身中是否含有该属性;
  使用in检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回true
  例子:
  function Person() {}
    Person.prototype.a = 123;
    Person.prototype.sayHello = function () {
      alert("hello");
    };
    var person = new Person()
    console.log(person.a)//123
    console.log(person.hasOwnProperty('a'));//false
    console.log('a'in person)//true
  
   实例上没有某属性,实例的原型也没有,如果还查不到,就去找原型的原型,一直找到最顶层Object为止。
   ObjectJS中所有对象数据类型的基类(最顶层的类)在Object.prototype上没有__proto__这个属性。
    console.log(Object.prototype.__proto__ === null) // true
    看图..

109 由懒加载:

当打包构建应用时,Javascript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。 结合 Vue 的异步组件和 Webpack 的代码分割功能,轻松实现路由组件的懒加载。

110 c3动画

     CSS3中的动画分为:平移动画、过渡动画和自定义动画三种。
  1 平移动画:transform: 平移translate / 旋转rotate / 放大scale / 倾斜skew;
  2 过渡动画:transition:  transition是一个复合属性,包括:
             transition-property:过渡属性(即哪些元素使用过渡动画);
             transition-delay:过渡延时;
             transition-duration:过渡时间;
             transition-timing-function:过渡方式(linear匀速播放,ease默认,以低速开始,然后加快,在结束前变慢。 )
             //注:如果写复合属性,当出现两个时间,则第一个为动画时间,第二个表示延时时间;如果只有一个时间,则表示的时动画时间。
  3 自定义动画(帧动画): animation: 动画名称   时间   运动方式   是否循环;
            1 animation-name: zidingyi; 动画名称;
            2 animation-delay: 1s ; 动画延迟时间;
            3 animation-direction: alternate; 动画的播放方向(alternate表示第135次正向播放,246次反向播放);
            4 animation-duration: 3s; 动画的播放时间;
            5 animation-iteration-count: 1; 动画的播放次数 (如果其后的属性值为infinite,则表示自定义的动画一直循环播放;
            6 animation-play-state:running | paused; 检索或设置对象动画的状态;
            7 animation-timing-function: linear; 动画的播放方式;
            8 animation-fill-mode:none | forwards对象状态为动画结束时的状态 | backwards | both 检索或设置对象动画时间之外的状态 
 
 动画播放序列的声明:(两种写法)
      @keyframes[空格] [定义的动画名]{
       方式一:from{ }
               to{ }
       使用“from”和“to”来代表一个动画是从哪开始,到哪结束。也就是说这个 “from"就相当于"0%”,而"to"相当于"100%"
       方式二:0%{ }
              30%{ }
              50%{ }
              80%{ }
              100%{ }

      keyframes的单位只接受百分比值
      transformanimation这两个属性不能同时使用,否则默认执行animation帧动画,transform属性无用,
      若要使用该属性,可以再给它包一个div,对这个div设置transform属性(不把两个属性用在同一元素下即可。)

111画一个三角形

#test3 {
    height:0;
    width:0;
    overflow: hidden;
    font-size: 0;
    line-height: 0;
    border-color:#FF9600 transparent transparent transparent;
    border-style:solid;
    border-width:20px;
}

#css3-triangle {
  width:0,
  height:0,
  border-left:100px solid transparent;
  border-right:100px solid transparent;
  border-bottom:150px solid #2322323;
}

112 iScorll插件上拉加载和下拉加载

113 一个加入购物车的动画效果

114 typeof与instanceof区别

js常用的基本数据类型包括undefinednullnumberbooleanstring;
js的引用数据类型也就是对象类型Object,比如:Object、array、function、data等;

typeof:
适用于基础数据类型判断,引用类型判断都是object
在判断null、array、object以及函数实例(new + 函数)时,得到的都是object(其实这也是原型继承)。
这使得在判断这些数据类型的时候,得不到真的数据类型。由此引出instanceof
a instanceof b:判断a是否为b的实例,可以用于继承关系中,instanceof 只能处理两个对象是否属于的实例关系
[] instanceof Object // true
[] instanceof Array // true
因为Array也是Object的实例对象,由于原型继承造成这种情况

解决办法:
1 Array.isArray()针对数组的操作 Array.isArray([]) 返回true
2 Object.prototype.toString.call('') === '[object String]' 判断是否是是字符串 返回true
    ===> Object.prototype.toString.call('')//[object String]
    ===> Object.prototype.toString.call({})//[object Object]
    ===> Object.prototype.toString.call([])//[object Array]
    ===> Object.prototype.toString.call(false)//[object Boolean]

115 vue全家桶

vue-router,vuex,vue-resource(官网里说这个不太好用,改用axios),vue-cli(不太算全家桶)

116vuex

    只用来读取的状态集中放在store中,改变状态的方式是提交mutations,这是个同步的事物; 异步逻辑应该封装在action中。


keep-alive是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。

css只在当前组件起作用->在style标签中写入scoped即可 例如:<style scoped></style>

v-if 和 v-show 区别->v-if按照条件是否渲染,v-show是display的block或none;

$route和$router的区别->$route是“路由信息对象”,包括path,params,hash,query, name等路由信息参数。
                      而$router是“路由实例”对象包括了路由的跳转方法,钩子函数等。

vue.js的两个核心是什么->数据驱动、组件系统

vue几种常用的指令->v-for 、 v-if 、v-bind、v-on、v-show、v-else

vue常用的修饰符->
.prevent: 提交事件不再重载页面;
.stop: 阻止单击事件冒泡;
.self: 当事件发生在该元素本身而不是子元素的时候会触发;
.capture: 事件侦听,事件发生的时候会调用

v-on 可以绑定多个方法吗->可以

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

什么是vue的计算属性?->
在模板中放入太多的逻辑会让模板过重且难以维护,在需要对数据进行复杂处理,且可能多次使用的情况下,尽量采取计算属性的方式

怎么定义 vue-router 的动态路由? 怎么获取传过来的值->
在 router 目录下的 index.js 文件中,对 path 属性加上 /:id,使用 router 对象的 params.id 获取。this.$route.params.id


117 vue等单页面应用及其优缺点

答:
优点:
Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件,
核心是一个响应的数据绑定系统。
MVVM、数据驱动、组件化、轻量、简洁、高效、快速、模块友好。

缺点:不支持低版本的浏览器,最低只支持到IE9;
不利于SEO的优化(如果要支持SEO,建议通过服务端来进行渲染组件);
第一次加载首页耗时相对长一些;不可以使用浏览器的导航按钮需要自行实现前进、后退。

118 写个递归啊~经典的递归函数

//斐波那契数列
//兔子数
//1小 1
//1中 1
//1大1小 2
//1大1中1小 3
//2大1中2小 5
//......
//当月的和=前两个月的和
//需求:求出来第12个月有多少兔子
function fn(n) {
  if(n==1 || n==2) {
  return 1;
  } 
  return fn(n-1)+fn(n-2);
}
console.log(fn(12)); 

119 hash和history两种模式的区别

  hash模式背后的原理是onhashchange事件,可以在window对象上监听这个事件,hash发生变化的url都会被浏览器记录下来,
  从而你会发现浏览器的前进后退都可以用了,同时点击后退时,页面也会发生变化
  history api可以分为两大部分,切换和修改,参考MDN,切换历史状态包括back、forward、go 三个方法,对应浏览器的前进,后退,跳转操作
  在前进后退上长按鼠标,会出来所有当前窗口的历史记录,从而可以跳转(也许叫跳更合适)
  通过history api,有个问题:不怕前进,不怕后退,就怕刷新,f5,(如果后端没有准备的话),
  因为刷新是实实在在地去请求服务器的,不玩虚的。 在hash模式下,前端路由修改的是#中的信息,
  而浏览器请求时是不带它玩的,所以没有问题.但是在history下,你可以自由的修改path,当刷新时,
  如果服务器中没有相应的响应或者资源,会分分钟刷出一个404来。

120webpack vue视频 打包的原理 node

121cook 不能存密码的原因

垂直居中兼容性问题 老浏览器  ie8  问题
数组
原理 awaite asinc 原理 Type of和什么什么的区别 

盒模型的组成:由里向外content,padding,border,margin.盒模型是有两种标准的,一个是标准模型,一个是IE模型。
在标准模型中,盒模型的宽高只是内容(content)的宽高,而在IE模型中盒模型的宽高是内容(content)+填充(padding)+边框(border)的总宽高。

122vue与React的区别

相同点:
  React采用特殊的JSX语法,Vue.js在组件开发中也推崇编写.vue特殊文件格式,对文件内容都有一些约定,两者都需要编译后使用;
  中心思想相同:一切都是组件,组件实例之间可以嵌套;
  都提供合理的钩子函数,可以让开发者定制化地去处理需求;
  都不内置列数AJAX,Route等功能到核心包,而是以插件的方式加载;
  在组件开发中都支持mixins的特性。
不同点:
  React采用的Virtual DOM会对渲染出来的结果做脏检查;
  Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷地操作Virtual DOM。