vue+js面试题精简版

1,响应式布局如何实现

响应式布局可以让网站同时适配不同分辨率和不同的手机端,让客户有更好的体验

方案一:百分比布局
    利用对属性设置百分比来适配不同屏幕,注意这里的百分比是对相对父元素,能够设置的属性有 width height padding margin 其他属性比如 border fort-size 不能百分比设置的
方案二:使用媒体查询(css3 @media查询)
	利用媒体查询设置不同分辨率下的css样式,来适配不同屏幕, 媒体查询相对于百分比布局,可以对布局进行更细致的调整,但需要在每个分辨率下面的都写一套css样式,分辨率拆分可视项目具体情况而定。注意:IE6.7.8毕业支持媒体查询
方案三:rem响应式布局
	当前页面中元素的rem,单位的样式值都是针对html元素的font-size的值进行动态计算的,所有有两种方法可以达到适配不同屏幕:第一种利用媒体查询,在不同分辨率下给html的font-size 赋值。 第二种利用js动态计算赋值。缺点就是打开页面的时候,元素大小会有一个变化过程。
方案四:vm 响应式布局
	根据PSD文件宽度或高度作为标准,元素单位px转换为vm或vh,比如font-size:12px
PSD文件宽度375,转换公式12*100/375,则样式改为font-size:3.2vm,
方案五:flex弹性布局
	利于flex属性来适配不同屏幕,利于display:flex 属性实现栏目响应式

2, rem 布局原理

rem:相对于根元素(即html元素)font-size 计算值得倍数。
通俗的说 1rme = html的font-size 值

如何使用rem进行布局?
1.标签的rem单位的值怎么计算
通过使用rem+js改变html标签的font-size(整体缩放)实现兼容性更高的页面下面举个例子,  当我们拿到的设计图是750px 的时候,窗口宽度750px,html的font-size的大小为100px。 也就是说1rem = 100px 所以标题的font-size的大小为26/100=26rem 。
2.如何实现兼容各种屏幕大小的设备
使用的javascript来动态改变html标签font-size的大小,其他的rem单位的数值就会被浏览动态计算转为px单位,从而达到和设计图高度的相似。 当屏幕750px的时候,html的font-size值是100px;窗口大小的变化的时候,可以通过js获取到窗口大小。 这个时候获取到一个比例750:100 = 获取到屏幕大小;html标签的px单位的值为以下js代码,用于实现根据获取到的屏幕的大小,动态的修改html标签的px单位的值

3,数据类型判断

1.typeof typeof对于基本数据类型判断是没有问题的,但是遇到引用数据类型(比如Array)是不起作用的
2.instanceof 判断new关键字创建的引用数据类型,不考虑null和undefind(这两个比较特殊) 以对象字面量创建的基本数据类型。
3.constructor constructor 似乎完全可以应对基本数据类型和引用数据类型,但如果声明了一个构造函数,并且把它的原型指向Array的原型,所有这种情况下,constructor也显得力不从心
4.Object.prototype.toString.call() 完美的解决方案.

4,原型和原型链

1原型的概念
javaScript的所有对象中都包含了一个proto内部属性,这个属性所对应的就是自身的原型。
javaScript的函数对象,除了原型proto之外,所有prototype属性,当函数对象作为构造函数创建实例时,该prototype属性值将被作为实例对象的原型proto。
2.原型链的概念
当一个对象调用自身不存在的属性或方法时,就会去自己的proto关联的前辈prototype对象上去找,如果没找到,就会去该prototype原型proto关联的前辈prototype去找,依次类推,直到找到属性或方法或undefined为止。从而形成了所谓的"原型链"。
3.总结
javaScript中的对象,都有一个内置属性prototype,指向这个对象的原型对象,当查找一个属性或方法时,如果在当前对象中找不到,会继续在当前对象的原型对象中查找。如果原型对象中依然没有找到,会继续在原型对象的原型中查找(原型也是对象,也有它自己的原型);直到找到为止,或者查找到最顶层的原型对象中也没有找到,就结束查找,返回undefined。这个查找过程是一个链式的查找,每个对象都有一个它自身原型对象的链接,这些链接组建的整个链条就是原型链,拥有相同原型的多个对象,他们的共同特征正是通过这种查找模式体现出来的。

在上面的查找过程, 我们提到了最顶层的原型对象, 这个对象就是Object.prototype,这个对象中保存了最常用的方法,如 toString、valueOf、hasOwnProperty 等,因此我们才能在任何对象中使用这些方法。

5,闭包

闭包的定义: 当一个函数的返回值是另外一个函数,而返回的那个函数如果调用了其父函数的内部变量,且返回的那个函数在外部被执行,就产生了闭包。

闭包的三个特性:
1.函数套函数,
2内部函数可以直接访问外部函数的内部变量或参数
3.变量或参数不会被垃圾回收机制回收

闭包的优点:变量长期驻扎在内存中,避免全局变量的污染,私有成员的存在。

闭包的缺点:常驻内存。增大内存的使用量,使用不当会造成内存泄露。

闭包的两种写法:
1,
function a(){
	var num = 1;
	function b(){
		alert(num)
	}
	return b   //把函数b返回给函数a
}
alert(a())   //弹出函数a,值是函数b;

2,
function a(){
	var num = 1;
	return function b(){
	alert(num=num+2)
	}
}
alert(a())  //弹出函数a,值是函数b;

调用方式:
1直接调用
a() //内部函数的执行

2.通过赋值再调用
var f = a();
f()

6,ji 继承

Es5 有 6 种方式可以实现继承,分别是:

1,原型链继承,原型链继承的基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。
缺点:1.通过原型来实现继承时,原型会变成另一个类型的实例,原先的实例属性变成了现在的原型属性,该原型的引用类型属性会被所有的实例共享。2.在创建子类型的实例时候,没有办法在不影响所有对象实例的情况下给超类型的构造函数中传递参数。

2,借用构造函数,借用构造函数的技术,其基本思想为:在子类型的构造函数中调用超类型构造函数。优点:1.可以向超类传递参数 2,解决了原型中包括引用类型值被所有实例共享的问题。 缺点:方法都在构造函数中定义,函数复用无从谈起,另外超类型原型中定义的方法对于类型而言都是不可见的。

3,组合继承(原型链+借用构造函数) 组合继承指的是将原型链和借用构造函数技术组合到一块,从而发挥二者之长的一种继承模式。基本思路:使用原型实现对原型属性的方法的继承,通过借用构造函数来实现对实例属性的继承,即通过在原型上定义方法来实现函数复用,又保证了每个实例都有自己的属性。 缺点:无论什么情况下,都会调用两次超类型构造函数,一次是在创建子类型原型的时候,另一次是在子类型构造函数内部。优点:可以向超类传递参数,每个实例都有自己的属性,实现了函数复用。

4.原型式继承 原型继承的基本思想;借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。

5.寄生式继承 寄生式继承是与原型式继承紧密相关的一种思路。寄生式继承的思路 与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数, 该函数在内部已某种方式来增强对象,最后再像真地是它做了所有工作一 样返回对象。缺点: 使用寄生式继承来为对象添加函数,会由于不能做到函数复用而效率低下。同原型链实现继承一样,包含引用类型值的属性会被所有实例共享。

6.寄生组合式继承 所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法,基本思路:不必为了指定子类型的原型而调用超类型的构造函数,我们需要的仅是超类型原型的一个副本,本质上就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。 优点:只调用了一次超类构造函数,效率更高。避免在 SuberType.prototype。上面创建不必要的、多余的属性,与其同时,原型链还能保持不变。因此寄生组合继承是引用类型最理性的继承范式。

7,什么是深拷贝,浅拷贝,如何实现

深拷贝和浅拷贝是针对复杂数据类型来说的,浅拷贝只拷贝一层,而深拷贝是层层拷贝。

深拷贝:深拷贝复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。 深拷贝后的对象与原来的对象是完全隔离的,互不影响, 对一个对象的修改并不会影响另一个对象。

浅拷贝:浅拷贝是会将对象的每个属性进行依次复制,但是当对象的属性值是引用类型时,实质复制的是其引用,当引用指向的值改变时也会跟着变化。可 以 使 用 for in 、 Object.assign 、 扩 展 运 算 符 … 、Array.prototype.slice()、Array.prototype.concat() 、递归等递归函数实现深拷贝

8,事件冒泡,事件捕获

什么是事件?

  事件是文档和浏览器窗口中发生的特定的交互瞬间。事件是javascript应用跳动的心脏,也是把所有东西黏在一起的胶水,当我们与浏览器中web页面进行某些类型的交互时,事件就发生了。
   事件可能是用户在某些内容上的点击,鼠标经过某个特定元素或按下键盘上的某些按键,事件还可能是web浏览器中发生的事情,比如某个web页面加载完成,或者是用户滚动窗口或改变窗口大小。

什么是事件流?

    事件流描述的是从页面中接受事件的顺序,但有意思的是,微软(IE)和网景开发团队居然提出了两个截然相反的事件流概念,IE的事件流是事件冒泡(event bubbling),而网景的事件流是事件捕获(event capturing)

事件冒泡和事件捕获的概念:

    事件冒泡和事件捕获是描述事件触发时候事件执行时序问题的术语,事件捕获指的是从document到触发事件的那个节点,也就是说自上而下的去触发事件,相反的 事件冒泡是自下而上的去触发事件,绑定事件方法的第三个参数,就是控制事件触发顺序是否为事件捕获,true为事件捕获,false为事件冒泡,jquery的e.stopPropagation  会阻止冒泡,意思就是到它为止,它的爹和祖宗的事件就不要触发了。

第一种:事件冒泡
   IE提出的事件流叫做事件冒泡,即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点。事件冒泡可以形象的比喻成把一颗石头投入水中,泡泡会一直从水底冒出水面,也就是说从小到大开始传播。

第二种:事件捕获
   网景公司提出的事件流叫事件捕获流。
   事件捕获流的思想是不太具体的DOM节点应该更早接收到事件,而最具体的节点应该最后接收的事件,针对上面同样的列子,点击按钮,那么此时 click事件会按照这样传播:下面我们就借用addEventListener的第三个参数来模拟事件捕获流,也就是上面的列子就会倒过来。 正如我们看到的,和冒泡流完全相反,从最不具体的元素接收到最具体的元素接收事件body=>div=>button=>p

9,h5 和 css3 的新特性

   h5每个人有每个人的理解,我的理接是h5并不是新增一些标签和样式更多的是里面新增的一些功能列如重力感应,他可以让我们感知当前手机的状态,可以帮助我们完成手机摇一摇。

h5新特性:
1语义化标签:header、footer、section、nav、aside、article
2增强型表单:input 的多个 type
3新增表单元素:datalist、keygen、output
4新增表单属性:placehoder、required、min 和 max
5音频视频:audio、video
6canvas
7地理定位
8拖拽
9本地存储:localStorage - 没有时间限制的数据存储;sessionStorage - 针对一个 session 的数据存储,当用户关闭浏览器窗口后,数据会被删除
10新事件:onresize、ondrag、onscroll、onmousewheel、onerror、onplay、onpause
11WebSocket:单个 TCP 连接上进行全双工通讯的协议

css3新特性:
1,选择器
2,背景和边框
3,文本效果
4,2D/3D 转换
5,动画、过渡,多列布局
6,户界面

10,Axios 拦截做过哪些

Axios 拦截分为请求拦截和响应拦截,请求拦截就是在你请求的时候会进行触发!只要你发送一个 axios 请求就会触发!所以我们主要用它做我们的 loding’ 加载和数据的权限验证,包括我们所有的数据预加载也可以实现,响应拦截主要是我们在 loading 加载,和做所有数据加载需要整体的结束,这个时候的结束就需要在数据马上发给前端的时候进行隐藏和结束,包括我们的请求头的设置,后端数据已经发送过来的时候,我们为了确保请求头的传递就必须在看看 header 里面是否有你需要的请求,如果有的话,再次进行设置!用 axios 拦截也可以配置公用地址,以及对于跨域问题解决,这个就是用 axios 拦截实现的功能。

11,sessionStorage locakStorage cookie 的区别

1. localStorage 生命周期是永久,这意味着除非用户显示在浏览器提供的UI 上清除 localStorage 信息,否则这些信息将永远存在。存放数据大小为一般为5MB,而且它仅在客户端(即浏览器)中保存,不参与和服务器的通信。

2.sessionStorage  仅在当前会话下有效,关闭页面或浏览器后被清除。存 放数据大小为一般为 5MB,而且它仅在客户端(即浏览器)中保存,不参与和服务器的通信。源生接口可以接受,亦可再次封装来对 Object 和 Array 有更好的支持。

作用域不同
不同浏览器无法共享 localStorage 或 sessionStorage 中的信息。相同浏览器的不同页面间可以共享相同的 localStorage(页面属于相同域名和端口),但是不同页面或标签页间无法共享 sessionStorage 的信息。这里需要注意的是,页面及标

3.cookie 的优点:具有极高的扩展性和可用性
1.	通过良好的编程,控制保存在 cookie 中的 session 对象的大小。
2.	通过加密和安全传输技术,减少 cookie 被破解的可能性。
3.	只有在 cookie 中存放不敏感的数据,即使被盗取也不会有很大的损失。
4.	控制 cookie 的生命期,使之不会永远有效。这样的话偷盗者很可能拿到的就是一个过期的 cookie。

4.	cookie 的缺点:
1.	cookie 的长度和数量的限制。每个 domain 最多只能有 20 条 cookie,每个cookie 长度不能超过 4KB。否则会被截掉。
2.	安全性问题。如果 cookie 被人拦掉了,那个人就可以获取到所有 session
信息。加密的话也不起什么作用。
3.	有些状态不可能保存在客户端。例如,为了防止重复提交表单,我们需要在服务端保存一个计数器。若吧计数器保存在客户端,则起不到什么作用。
localStorage、sessionStorage、Cookie 共同点:都是保存在浏览器端,且同 源的。

12,图片懒加载实现原理

什么是懒加载?
懒加载突出一个“懒”字,懒就是拖延迟的意思,所以“懒加载”说白了就是延迟加载,比如我们加载一个页面,这个页面很长很长,长到我们的浏览器可视区域装不下,那么懒加载就是优先加载可视区域的内容,其他部分等进入了可视区域在加载。

为什么要懒加载?
懒加载是一种网页性能优化的方式,它能极大的提升用户体验。就比如说图片,图片一直是影响网页性能的主要元凶,现在一张图片超过几兆已经是很经常的事了。如果每次进入页面就请求所有的图片资源,那么可能等图片加载
出来用户也早就走了。所以,我们需要懒加载,进入页面的时候,只请求可视区域的图片资源。

总结出来就两个点:1.	全部加载的话会影响用户体验
2.	浪费用户的流量,有些用户并不像全部看完,全部加载会耗费大量流量。

懒加载的实现原理?。
由于网页中占用资源较多的一般是图片,所以我们一般实施懒加载都是对图
片资源而言的,所以这里的实现原理主要是针对图片。
大家都知道,一张图片就是一个标签,而图片的来源主要是 src 属性。浏览器是否发起亲求就是根据是否有 src 属性决定的。
既然这样,那么我们就要对标签的 src 属性下手了,在没进入可视区域的时候,我们先不给这个标签赋 src 属性,这样岂不是浏览器就不会发送请求了。

13,瀑布流原理

瀑布流又称瀑布流式布局,是比较流行的一种网站页面布局方式
视觉表现为参差不齐的多栏布局,最早采用此布局的是网站是 Pinterest, 后逐渐在国内流行即多行等宽元素排列,后面的元素依次添加到其后,等宽不等高,根据图片原比例缩放直至宽度达到我们的要求,依次按照规则放入指定位置。

总结瀑布流布局原理:
瀑布流的实现原理就是通过比较每一列的高度,如果这一列高度低的话就在这一列进行添加,如果可视区距离和滚动距离想加的话比你当前页面的高度还要高的时候,页面就开再次加载多个,这个主要也是页面布局,如果你的布局实现的不好的话!也会出现问题,首先每一列的高度,都是需要自适应的,不能设置高通过每一块内容将每一列撑起来,还有一个问题就是,滑动底部,根据每个电脑的不同,所以他每个人,获取的高度是不同而且有的时候,页面的整体高度和页面可视区高度加上滚动高度差 1px 这个时候就需要我们提前加载,不然滑动到底部也加载不出来!

14,meta 标签内属性及详情

name 属性
1.keywords
用于告诉搜索引擎,你网页的关键字。举例:

2.description
用于告诉搜索引擎,你网站的主要内容。举例:

3. viewport(移动端的窗口)

4.robot
robots用来告诉爬虫哪些页面需要索引,哪些页面不需要索引。content的参数有all,none,index,noindex,follow,nofollow。默认是all。
举例:
5.author
用于标注网页作者

6.generator(网页制作软件)

7.copyright(版权)

8.revisit-after(重访)
如果页面不是经常更新,为了减轻搜索引擎爬虫对服务器带来的压力,可以设置一个爬虫的重访时间。如果重访时间过短,爬虫将按它们定义的默认时间来访问

9.renderer
renderer是为双核浏览器准备的,用于指定双核浏览器默认以何种方式渲染页面。比如说360浏览器。
 //默认webkit内核
 //默认IE兼容模式
 //默认IE标准模式
http-equiv属性
http-equiv顾名思义,相当于http的文件头作用,它可以向浏览器传回一些有用的信息,以帮助正确和精确地显示网页内容,与之对应的属性值为content,content中的内容其实就是各个参数的变量值。
10.Expires(期限)
说明:可以用于设定网页的到期时间。一旦网页过期,必须到服务器上重新传输

注意:必须使用GMT的时间格式。
11.Pragma(cache模式)
说明:禁止浏览器从本地计算机的缓存中访问页面内容。

注意:这样设定,访问者将无法脱机浏览。
12.Refresh(刷新)
说明:自动刷新并指向新页面。
 (注意后面的分号,分别在秒数的前面和网址的后面)
注意:其中的2是指停留2秒钟后自动刷新到URL网址
13.Set-Cookie(cookie设定)
说明:如果网页过期,那么存盘的cookie将被删除。
用法:
注意:必须使用GMT的时间格式
14.Window-target(显示窗口的设定)
说明:强制页面在当前窗口以独立页面显示。
用法:
注意:用来防止别人在框架里调用自己的页面
15.content-Type(显示字符集的设定)
说明:设定页面使用的字符集。
用法:
注意:HTML5中使用  来设定
meta标签的charset的信息参数如GB2312时,代表说明网站是采用的编码是简体中文;
meta标签的charset的信息参数如BIG5时,代表说明网站是采用的编码是繁体中文;
meta标签的charset的信息参数如iso-2022-jp时,代表说明网站是采用的编码是日文;
meta标签的charset的信息参数如ks_c_5601时,代表说明网站是采用的编码是韩文;
meta标签的charset的信息参数如ISO-8859-1时,代表说明网站是采用的编码是英文;
meta标签的charset的信息参数如UTF-8时,代表世界通用的语言编码;
16.content-Language(显示语言的设定)
用法:
17.Cache-Control指定请求和响应遵循的缓存机制。
Cache-Control指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置Cache-Control并不会修改另一个消息处理过程中的缓存处理过程。请求时的缓存指令包括no-cache、no-store、max-age、max-stale、min-fresh、only-if-cached,
响应消息中的指令包括public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age。
各个消息中的指令含义如下
Public指示响应可被任何缓存区缓存
Private指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效
no-cache指示请求或响应消息不能缓存
no-store用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。
max-age指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应
min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应
max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。


15 解构赋值

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)
解构赋值,左右结构必须一样,使用左边定义的值,快速的取出数据中对应的数据值,而且 定义和赋值必须放到一起,不然的话就会报错,取不出来数据值,而且左边也必须是一个 js 存在数据结构不然的话也会报错,解构赋值的主要作用还是,快速的让我们在数据中抓取出我们想要的数据。

16,对 BFC 规范(块级格式化上下文:block formatting context)的理解?

BFC规定了内部的Block Box如何布局。
定位方案:
内部的Box会在垂直方向上一个接一个放置。
Box垂直方向的距离由margin决定,属于同一个BFC的两个相邻Box的margin会发生重叠。
每个元素的margin box 的左边,与包含块border box的左边相接触。
BFC的区域不会与float box重叠。
BFC是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。
计算BFC的高度时,浮动元素也会参与计算。

满足下列条件之一就可触发BFC:
根元素,即html
float的值不为none(默认)
overflow的值不为visible(默认)
display的值为inline-block、table-cell、table-caption
position的值为absolute或fixed

17. async/await

Async 和 await 是一种同步的写法,但还是异步的操作,两个内容还是必须同时去写才会生效不然的话也是不会好使,而且 await 的话有一个不错的作用就是可以等到你的数据加载过来以后才会去运行下边的 js 内容,而且 await 接收的对象必须还是个 promise 对象,如果是接收数据的时候就可以直接用一句话来接收数据值,所以这个 async await 我的主要应用是在数据的接收,和异步问题的处理,主要是还是解决不同执行时机下的异步问题!

17.es6 有哪些拓展

1.	新增了块级作用域(let,const)
2.	提供了定义类的语法糖(class)
3.	新增了一种基本数据类型(Symbol)
4.	新增了变量的解构赋值
5.	函数参数允许设置默认值,引入了 rest 参数,新增了箭头函数
6.	数组新增了一些 API,如 isArray / from / of 方法;数组实例新增了
entries(),keys() 和 values() 等方法
7.	对象和数组新增了扩展运算符
8.	ES6 新增了模块化(import/export)
9.	ES6 新增了 Set 和 Map 数据结构
10.	ES6 原生提供 Proxy  构造函数,用来生成 Proxy 实例
11.	ES6 新增了生成器(Generator)和遍历器(Iterator)

18.请写出在 vue 中使用 promise 封装项目 api 接口的思路?

axios 封装了原生的 XHR,让我们发送请求更为简单,但假设在一个成百上千个 vue 文件的项目中,我们每一个 vue 文件都要写 axios.get()或 axios.post() 岂不是很麻烦?后期的维护也不方便,所以我们要对 axios 进行进一步的封装。

1.构赋 vue-cli 项目的目录如上,我们在原有的目录基础上新建 api 与 utils

在 request.js 中做了三件事
1.	创建 axios,设置 baseURL 与超时时间
2.	拦截请求
3.	拦截响应
4.	路由拦截

19, promise 是什么?有哪些状态和参数?如何使用?

1、主要用于异步计算
2、可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
3、可以在对象之间传递和操作 promise,帮助我们处理队列
resolve 作用是,将 Promise 对象的状态从“未完成”变为“成功”(即从 pending  变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject 作用是,将 Promise 对象的状态从“未完成”变为“失败”(即从 pending  变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

promise 有三个状态:
1、pending[待定]初始状态2、fulfilled[实现]操作成功
3、rejected[被否决]操作失败
当 promise 状态发生改变,就会触发 then()里的响应函数处理后续步骤; promise 状态一经改变,不会再变。
Promise 对象的状态改变,只有两种可能: 从 pending 变为 fulfilled
从 pending 变为 rejected。
这两种情况只要发生,状态就凝固了,不会再变了。

20, for…in 迭代和 for…of 有什么区别

1、推荐在循环对象属性的时候,使用 for...in,在遍历数组的时候的时候使用for...of。
2、for...in 循环出的是 key,for...of 循环出的是 value
3、注意,for...of 是 ES6 新引入的特性。修复了 ES5 引入的 for...in 的不足
4、for...of 不能循环普通的对象,需要通过和 Object.keys()搭配使用

21, generator(异步编程、yield、next()、await 、async)

提示:Generator 是一个迭代器生成函数,其返回值是一个迭代器(Iterator),可用于异步调用。
比如某个事物只有三种状态(状态 A,状态 B,状态 C),而这三种状态的变化是状态 A =>状态 B =>状态 C =>状态 A ,这就是状态机。Generator 特别适用于处理这种状态机

22, Ajax 是什么?以及如何创建 Ajax?

1、Ajax 并不算是一种新的技术,全称是 asychronous javascript and xml,
可以说是已有技术的组合,主要用来实现客户端与服务器端的异步通信效果,实现页面的局部刷新,早期的浏览器并不能原生支持 ajax,可以使用隐藏帧(iframe)方式变相实现异步效果,后来的浏览器提供了对 ajax 的原生支持 .
2、使用 ajax 原生方式发送请求主要通过 XMLHttpRequest( 标准浏览
器 ) 、 ActiveXObject(IE 浏览器)对象实现异步通信效果 .

3、基本步骤:
javascript
var xhr =null;//创建对象if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
xhr.open(“方式”,”地址”,”标志位”);//初始化请求xhr.setRequestHeader(“”,””);//设置 http  头信息

xhr.onreadystatechange =function(){}//指定回调函数 xhr.send();//发送请求

4、js  框架(jQuery/EXTJS  等)提供的 ajax API  对原生的 ajax  进行了封
装,熟悉了基础理论,再学习别的框架就会得心应手,好多都是换汤不换药的内容

23, 什么是跨域,以及 jsonp 的原理?

1、理解跨域的概念:协议、域名、端口都相同才同域,否则都是跨域
2、出于安全考虑,服务器不允许 ajax 跨域获取数据,但是可以跨域获取文件内容,所以基于这一点,可以动态创建 script 标签,使用标签的 src 属性访问 js 文件的形式获取 js 脚本,并且这个 js 脚本中的内容是函数调用,该函数调用的参数是服务器返回的数据,为了获取这里的参数数据,需要事先在页面中定义回调函数,在回调函数中处理服务器返回的数据,这就是解决跨域问题的jsonp原理。

24, 跨域的解决方式有哪些

答:产生跨域的情况有:不同协议,不同域名,不同端口以及域名和 ip 地址的访问都会产生跨域。

跨域的解决方案目前有三种主流解决方案:
是 jsonp
jsonp 实现原理:主要是利用动态创建 script 标签请求后端接口地址,然后传递 callback 参数,后端接收 callback,后端经过数据处理,返回 callback 函数调用的形式,callback 中的参数就是 json
优点:浏览器兼容性好,
缺点:只支持 get 请求方式
是代理(前端代理和后端通常通过 nginx 实现反向代理)
前端代理我在vue 中主要是通过vue 脚手架中的config 中的index 文件来配置的,其中有个 proxyTable 来配置跨域的
前端代理核心实现通过 http-proxy-middleware 插件来实现的,vue2.x 和
vue3.x 脚手架代理跨域实现原理是一样的是 CORS
CORS 全称叫跨域资源共享,主要是后台工程师设置后端代码来达到前端跨域请求的
CORS 的原理:CORS 定义一种跨域访问的机制,可以让 AJAX 实现跨域访问。 CORS 允许一个域上的网络应用向另一个域提交跨域 AJAX 请求。实现此功能非常简单,只需由服务器发送一个响应标头即可。

优点:无需前端工程师设置,只需后端工程师在请求的页面中配置好,并且支持所有请求方式(例如:get,post,put,delete 等)
缺点:浏览器支持有版本要求,如下:
chrome:13+,firefox:3.5+,IE 11+,edge:12+
注:现在主流框架都是用代理和 CORS 跨域实现的

25, 说一下从输入 URL 到页面加载完中间发生了什么?

答:大致过程是这样的:
1.	DNS 解析
2.	TCP 连接
3.	发送 HTTP 请求
4.	服务器处理请求并返回需要的数据
5.	浏览器解析渲染页面
6.	连接结束
注:这里会延伸出问 http 状态码,和三次握手和四次挥手相关问题:

26, Vue 中 methods,computed, watch 的区别

1)	methods 中都是封装好的函数,无论是否有变化只要触发就会执行适用场景:组件中功能的封装,逻辑处理
2)	computed:是 vue 独有的特性计算属性,可以对 data 中的依赖项再重新计算得到一个新值,应用到视图中,和 methods 本质区别是 computed 是可缓存的, 也就是说 computed 中的依赖项没有变化,则 computed 中的值就不会重新计算, 而 methods 中的函数是没有缓存的。
适用场景:假设我们有一个性能开销比较大的计算属性	A,它需要遍历一
个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于	A	。如果没有缓存,我们将不可避免的多次执行某个函数
3)	Watch 是监听 data 和计算属性中的新旧变化
适用场景:当需要在数据变化时执行“异步”或“开销较大”的操作时,这个方式是最有用的

27, prop 验证,和默认值

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。子组件想修改时,只能通过 $emit 派发一个自定义事件,父组件接收到后,由父组件修改。
有两种常见的试图改变一个 prop 的情形 :
(1)	这个用来传递一个初始值;这个子组件接下来希望将其作为一个本地的数据来使用。 在这种情况下,最好定义一个本地的属性并将这个用作其初始值:
(2)	这个以一种原始的值传入且需要进行转换。 在这种情况下,最好使用这个的值来定义一个计算属性

28,vue 双向数据绑定原理

1、实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
2、实现一个指令解析器 Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
3、实现一个 Watcher,作为连接 Observer 和 Compile 的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图

29,vue 组件父子,子父,兄弟通信

第一种:父传子:主要通过 props 来实现的
具体实现:父组件通过 import 引入子组件,并注册,在子组件标签上添加要传递的属性,子组件通过 props 接收,接收有两种形式一是通过数组形式[‘要接收的属性’ ],二是通过对象形式{ }来接收,对象形式可以设置要传递的数据类型和默认值,而数组只是简单的接收

第二种:子传父:主要通过$emit 来实现
具体实现: 子组件通过通过绑定事件触发函数, 在其中设置this.$emit(‘要派发的自定义事件’,要传递的值),$emit 中有两个参数一是要派发的自定义事件,第二个参数是要传递的值

第三种:兄弟之间传值有两种方法: 方法一:通过 event bus 实现
具体实现:创建一个空的 vue 并暴露出去,这个作为公共的 bus,即当作两个组件的桥梁,在两个兄弟组件中分别引入刚才创建的bus,在组件 A 中通过 bus.$emit(’自定义事件名’,要发送的值)发送数据,在组件 B中通过 bus.$on(‘自定义事件名‘,function(v) { //v 即为要接收的值 })接收数据

方法二:通过 vuex 实现
具体实现:vuex 是一个状态管理工具,主要解决大中型复杂项目的数据共享问题,主要包括 state,actions,mutations,getters 和 modules 5 个要素,主要流程:组件通过 dispatch 到 actions,actions 是异步操作,再 actions中通过 commit 到 mutations,mutations 再通过逻辑操作改变 state,从而同步到组件,更新其数据状态

30,vue 生命周期

beforeCreate( 创建前 )
在实例初始化之后,数据观测和事件配置之前被调用,此时组件的选项对象还未创建,el 和 data  并未初始化,因此无法访问 methods, data, computed 等上的方法和数据。
created ( 创建后)
实例已经创建完成之后被调用,在这一步,实例已完成以下配置:数据观测、属性和方法的运算,watch/event 事件回调,完成了 data 数据的初始化,el 没有。然而,挂载阶段还没有开始, $el 属性目前不可见,这是一个常用的生命周期, 因为你可以调用 methods 中的方法,改变 data 中的数据,并且修改可以通过 vue 的响应式绑定体现在页面上,,获取 computed 中的计算属性等等,通常我们可
以在这里对实例进行预处理,也有一些童鞋喜欢在这里发 ajax 请求,值得注意的是,这个周期中是没有什么方法来对实例化过程进行拦截的,因此假如有某些数据必须获取才允许进入页面的话,并不适合在这个方法发请求,建议在组件路由钩子 beforeRouteEnter 中完成
beforeMount
挂在开始之前被调用,相关的 render 函数首次被调用(虚拟 DOM),实例已完成以下的配置:编译模板,把 data 里面的数据和模板生成 html,完成了 el 和 data 初始化,注意此时还没有挂在 html 到页面上。
mounted
挂在完成,也就是模板中的 HTML 渲染到 HTML 页面中,此时一般可以做一些 ajax 操作,mounted 只会执行一次。
beforeUpdate
在数据更新之前被调用,发生在虚拟 DOM 重新渲染和打补丁之前,可以在该钩子中进一步地更改状态,不会触发附加地重渲染过程
updated(更新后)
在由于数据更改导致地虚拟 DOM 重新渲染和打补丁只会调用,调用时,组件 DOM 已经更新,所以可以执行依赖于 DOM 的操作,然后在大多是情况下, 应该避免在此期间更改状态,因为这可能会导致更新无限循环,该钩子在服务器端渲染期间不被调用
beforeDestrioy (销毁前)
在实例销毁之前调用,实例仍然完全可用,

这一步还可以用 this 来获取实例,
一般在这一步做一些重置的操作,比如清除掉组件中的定时器和监听的dom
事件
destroyed(销毁后)
在实例销毁之后调用,调用后,所以的事件监听器会被移出,所有的子实例也会被销毁,该钩子在服务器端渲染期间不被调用

31、 vue 路由传参数如何实现

主要通过 query 和 params 来实现
query 传参:通过在 router-link 或this.$router.push()传递 url 地址并且拼接? 问号传递的参数 例如:rourer-link to=”/goods?id=1001”,然后在接收的页面通过 this.$route.query.id 来接收
优点:通用性比较好,刷新数据不会丢失
params 传参:通过在 router-link 或 this.$router.push()传递 url 地址并且拼接的参数也用/来表示 例如:rourer-link to=”/goods/1001”,并且在路由页面通过 routes=[{path:’/goods/:id’}]配置,最后在接收的页面通过 this.$route.params.id来接收
优点:传递数据量在,优雅
缺点:刷新数据不会丢失

32,路由导航守卫有几种,如何实现

一、全局路由守卫
所谓全局路由守卫,就是小区大门,整个小区就这一个大门,你想要进入其中任何一个房子,都需要经过这个大门的检查
全局路由守卫有个两个:一个是全局前置守卫,一个是全局后置守卫
router.beforeEach((to, from, next) => { console.log(to) => // 到哪个页面去? console.log(from) => // 从哪个页面来? next() => // 一个回调函数
}
router.afterEach(to,from) = {} next():回调函数参数配置
next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址
next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: true、name: 'home' 之类的选项以及任何用在 router-link 的 to prop 或 router.push 中的选项

二、组件路由守卫
// 跟 methods: {}等同级别书写,组件路由守卫是写在每个单独的 vue 文件里面的路由守卫
beforeRouteEnter (to, from, next) {
// 注意,在路由进入之前,组件实例还未渲染,所以无法获取 this 实例,只能通过 vm 来访问组件实例
next(vm => {})
}
beforeRouteUpdate (to, from, next) {
// 同一页面,刷新不同数据时调用,
}
beforeRouteLeave (to, from, next) {
// 离开当前路由页面时调用
}

三、路由独享守卫
路由独享守卫是在路由配置页面单独给路由配置的一个守卫
export default new VueRouter({ routes: [

{
path: '/',
name: 'home', component: 'Home',
beforeEnter: (to, from, next) => {
// ...
}
}
]
}

33,vuex 中 state ,getters,mutations,actions,modules,plugins 的用途,和用法。

state:存储状态(变量)
getters:对数据获取之前的再次编译,可以理解为 state 的计算属性。我们在组件中使用 $sotre.getters.fun()
mutations : 修 改 状 态 , 并 且 是 同 步 的 。 在 组 件 中 使 用
$store.commit('',params)。这个和我们组件中的自定义事件类似。actions:异步操作。在组件中使用是$store.dispath('')
modules:store 的子模块,为了开发大型项目,方便状态管理而使用的。这里我们就不解释了,用起来和上面的一样。

34,vue 中 key 的作用

“key 值:用于管理可复用的元素。因为 Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。这么做使 Vue 变得非常快,但是这样也不总是符合实际需求。 2.2.0+ 的版本里,当在组件中使用 v-for 时,key 是必须的。

35,vue 常用修饰符

.stop: 阻止点击事件冒泡。等同于 JavaScript 中的 event.stopPropagation()
使用了.stop 后,点击子节点不会捕获到父节点的事件
.prevent 防止执行预设的行为(如果事件可取消,则取消该事件,而不停止事件的进一步传播),等同于 JavaScript 中的 event.preventDefault(),prevent  等同于 JavaScript 的 event.preventDefault(),用于取消默认事件。
.capture 与事件冒泡的方向相反,事件捕获由外到内,捕获事件:嵌套两三层父子关系,然后所有都有点击事件,点击子节点,就会触发从外至内父节点-》子节点的点击事件
.self 只会触发自己范围内的事件,不包含子元素
.once 只执行一次,如果我们在@click 事件上添加.once 修饰符,只要点击按钮只会执行一次。
.passive Vue 还对应 addEventListener 中的 passive 选项提供了 .passive
修饰符

36,vue 自定义指令如何使用

【全局指令】
使用 Vue.diretive()来全局注册指令。
【局部指令】
也可以注册局部指令,组件或 Vue 构造函数中接受一个 directives 的选项。

钩子函数。指令定义函数提供了几个钩子函数(可选)。
【bind】
只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。

【inserted】
被绑定元素插入父节点时调用( 父节点存在即可调用, 不必存在于
document 中)。
【update】
所在组件的 VNode 更新时调用,但是可能发生在其孩子的 VNode 更新之前。指令的值可能发生了改变也可能没有。但是可以通过比较更新前后的值来忽略不必要的模板更新。
【componentUpdated】
所在组件的 VNode 及其孩子的 VNode 全部更新时调用。
【unbind】
只调用一次,指令与元素解绑时调用。钩子函数参数
钩子函数被赋予了以下参数
【el】
指令所绑定的元素,可以用来直接操作 DOM。
【binding】
一个对象,包含以下属性:
name: 指令名,不包括 v- 前缀。
value: 指令的绑定值,例如: v-my-directive="1 + 1", value 的值是 2。oldValue: 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression: 绑定值的字符串形式。例如 v-my-directive="1 + 1" , expression
的值是 "1 + 1"。
arg: 传给指令的参数。例如 v-my-directive:foo, arg  的值是 "foo"。 modifiers: 一个包含修饰符的对象。例如:  v-my-directive.foo.bar,   修饰符对象 modifiers 的值是 { foo: true, bar: true }。

37,keep-alive 的作用

1、 在 vue 项目中,难免会有列表页面或者搜索结果列表页面,点击某个结果之后,返回回来时,如果不对结果页面进行缓存,那么返回列表页面的时候会回到初始状态,但是我们想要的结果是返回时这个页面还是之前搜索的结果列表,这时候就需要用到 vue 的 keep-alive 技术了.
2、 在 router-view 上使用可以缓存该路由组件
3、 有两个参数 include - 字符串或正则表达,只有匹配的组件会被缓存
exclude - 字符串或正则表达式,任何匹配的组件都不会被缓存
1、语法 Object.defineProperty(obj, prop, descriptor)
2、定义:Object.defineProperty()   直接在一个对象上定义一个新属性,或者修改现有属性,并返回该对象。
3、参数
obj 要在其上定义属性的对象。
prop 要定义或修改的属性的名称。
descriptor 将被定义或修改的属性描述符。
4、返回值
返回被操作的对象,即返回 obj 参数
5、注意点
1)	当把 configurable 值设置为 false 后,就不能修改任何属性了,包括自己本身这个属性
2)	想用访问器属性模拟默认行为的话,必须得在里面新顶一个属性,不然的话会造成循环引用
3)	可枚举属性对 for/in, Object.keys(), JSON.stringify(), Object.assign()  方法才生效(for/in 是对所有可枚举属性,而其他三种是对自身可枚举属性)

6、用途
1)	vue 通过 getter-setter 函数来实现双向绑定
2)	俗称属性挂载器
3)	专门监听对象数组变化的 Object.observe()(es7)也用到了该方法

38,什么是虚拟 dom,和 diff 算法

1、虚拟 DOM 的最终目标是将虚拟节点渲染到视图上。但是如果直接使用虚拟节点覆盖旧节点的话,会有很多不必要的 DOM 操作。例如,一个 ul 标签下很多个 li 标签,其中只有一个 li 有变化,这种情况下如果使用新的 ul 去替代旧的 ul,因为这些不必要的 DOM 操作而造成了性能上的浪费。
为了避免不必要的DOM 操作,虚拟 DOM 在虚拟节点映射到视图的过程中, 将虚拟节点与上一次渲染视图所使用的旧虚拟节点(oldVnode)做对比,找出真正需要更新的节点来进行  DOM 操作,从而避免操作其他无需改动的 DOM。
简而言之主要做了两件事:
提供与真实DOM 节点所对应的虚拟节点 vnode 将虚拟节点vnode 和旧虚拟节点 oldVnode 进行对比,然后更新视图
2、diff 算法包括几个步骤:
a.	用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中
b.	当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异
c.	把所记录的差异应用到所构建的真正的 DOM 树上,视图就更新了

39, vue 中数组中的某个对象的属性发生变化,视图不更新如何解决

问题原因:因为 vue 的检查机制在进行视图更新时无法监测 数组中的某个对象的属性值的变化。解决方案如下
方案一:利用  this.set(this.obj,key,val)
例:this.set(this.obj,‘k1’,‘v1’)
方案二:就利用 Object.assign({},this.obj)创建新对象如果是数组就 Object.assign([],this.obj)
如果是对象就 Object.assign({},this.obj)

40.vue3.0 与 vue2.0 的区别

1、性能提升
一句话简介:更小巧,更快速;支持摇树优化;支持 Fragments 和跨组件渲染;支持自定义渲染器。
2、API 变动
一句话介绍:除渲染函数 API 和 scoped-slot 语法之外,其余均保持不变或者将通过另外构建一个兼容包	来兼容 2.x。
模板语法的 99% 将保持不变。除了 scoped slot 语法可能会有一些微调之外变动最大的部分将是渲染函数	(render) 中的虚拟 DOM 的格式。
3、重写虚拟 DOM (Virtual DOM Rewrite)
随着虚拟 DOM 重写,减少 运行时(runtime)开销。重写将包括更有效的代码来创建虚拟节点。

你可能感兴趣的:(面试题,javascript,vue.js)