目录
目录
2.js有几种数据类型?null与undefined的区别?
1.盒子模型
一个盒子中主要的属性就5个:width、height、padding(内边距)、border、margin(外边距)。
盒模型有标准盒模型和IE的盒模型,
IE盒模型:
不同之处就是标准盒模型的内容大小就是content的大小,
而IE的则是content + padding +border 总的大小。
那么随之而来第二个问题–怎么设置这两种模型呢?
很简单,通过设置 box-sizing:content-box(W3C)/border-box(IE)就可以达到自由切换的效果。
2.js有几种数据类型?null与undefined的区别?
JS有7种数据类型:三种基本类型(数字,字符串,布尔),两种引用数据类型(对象,数组),两种特殊数据类型(undefined,null)
其中上面的四种(undefined, number, string, boolean)属于简单的值类型,不是对象。
剩下的几种情况——函数、数组、对象、null、new Number(10)都是对象。他们都是引用类型。
值类型的类型判断用typeof,引用类型的类型判断用instanceof。
null与undefined的区别
undefined表示"缺少值",就是此处应该有一个值,但是还没有定义,undefined类型只有一个值,undefined.
(1)所有已声明但是没有初始化的变量,默认值都为undefined。
(2)函数没有明确返回值的时候,会默认返回undefined。
null为一个空指针对象null表示"没有对象",即该处不应该有值
当函数返回的对象不存在时,返回null。
当某个对象不需要时,可将值设为null。
3.js闭包
闭包是指有权访问另一个函数作用域变量的函数。
清晰的讲:闭包就是一个函数,这个函数能够访问其他函数的作用域中的变量。
创建闭包的通常方式,是在一个函数内部创建另一个函数。
由于作用域链的结构,外围函数是无法访问内部变量的,为了能够访问内部变量,我们就可以使用闭包,闭包的本质还是函数
4.重绘和回流
只是样式的变化,不会引起DOM树变化,页面布局变化的行为叫重绘,且重绘不一定会伴随回流
引起DOM树结构变化,页面布局变化的行为叫回流,且回流一定伴随重绘。
什么情况下回导致回流,如何避免回流?
1.页面初次渲染
2.浏览器窗口尺寸改变
resize事件发生也会引起回流。
3.DOM的增删行为
比如你要删除某个节点,给某个父元素增加子元素,这类操作都会引起回流。
如果要加多个子元素,最好使用documentfragment。(让要操作的元素进行离线处理,处理完事以后再一起更新)
documentFragment是一个保存多个element的容器对象(保存在内存)当更新其中的一个或者多个element时,页面不会更新。只有当documentFragment容器中保存的所有element更新后再将其插入到页面中才能更新页面。
documentFragment用来批量更新
4.几何属性的变化
比如元素宽高变了,border变了,字体大小变了,这种直接会引起页面布局变化的操作也会引起回流。
如果你要改变多个属性,最好将这些属性定义在一个class中,直接修改class名,这样只用引起一次回流。
5.元素位置的变化
改一个元素的左右margin,padding之类的操作
所以在做元素位移的动画,不要更改margin之类的属性,使用定位脱离文档流后改变位置会更好
5.本地存储和离线缓存
5.1本地存储
1.cookie
(1)在h5之前,存储主要用的是cookie。cookie会随着每次http请求头信息一起发送,无形中增加了网络流量,另外,cookie能存储的数据容量有限,根据浏览器类型不同而不同
(2)cookie的优缺点
优点:
- 可控制过期时间,使其不会长期有效
- 可扩展、可用性比较好
- 可加密减少cookie被破解的可能性
缺点:
- 数量和长度有限制,最多20条,最长不能超过4k
- 在请求头上带着数据安全性差
(3)cookie的应用场景:主要应用:购物车、客户端登录
2.localStorage
(1)localStorage(本地存储),可以长期存储数据,没有时间限制,一天,一年,两年甚至更长,数据都可以使用
(2)优缺点
- 优点:
localStorage拓展了cookie的4k限制
localStorage可以将第一次请求的5M大小数据直接存储到本地,相比于cookie可以节约带宽
localStorage的使用也是遵循同源策略的,所以不同的网站直接是不能共用相同的localStorage - 缺点:
需要手动删除,否则长期存在
浏览器大小不一,版本的支持也不一样
localStorage只支持string类型的存储,JSON对象需要转换
localStorage本质上是对字符串的读取,如果存储内容多的话会消耗内存空间,会导致页面变卡 - 特点:
同源策略限制、只在本地存储、永久保存、同浏览器共享
(3)应用场合
- 数据比较大的临时保存方案。如在线编辑文章时的自动保存。
- 多页面访问共同数据。sessionStorage只适用于同一个标签页,localStorage相比而言可以在多个标签页中共享数据。
3.sessionStorage会话存储
(1)sessionStorage(会话存储),只有在浏览器被关闭之前使用,创建另一个页面时同意可以使用,关闭浏览器之后数据就会消失
(2)特点
- 同源策略限制。若想在不同页面之间对同一个sessionStorage进行操作,这些页面必须在同一协议、同一主机名和同一端口下。
- 单标签页限制。sessionStorage操作限制在单个标签页中,在此标签页进行同源页面访问都可以共享sessionStorage数据。
- 只在本地存储。seesionStorage的数据不会跟随HTTP请求一起发送到服务器,只会在本地生效,并在关闭标签页后清除数据
- 存储方式。seesionStorage的存储方式采用key、value的方式。value的值必须为字符串类型(传入非字符串,也会在存储时转换为字符串。)。
- 存储上限限制:不同的浏览器存储的上限也不一样,但大多数浏览器把上限限制在5MB以下。
(3)应用场合:sessionStorage 非常适合单页应用程序,可以方便在各业务模块进行传值。
5.2离线缓存
Application Cache (Manifest)
1)使用方法:
1> 在html标签添加manifest属性
在页面的html标签中添加manifest属性,属性值为manifest文件的路径。如:
<!DOCTYPE HTML>
<html manifest="../js/demo.manifest">
...
</html>
2)编写manifest文件
manifest文件是简单的文本文件,它会告知浏览器需要缓存的内容以及不需要缓存的内容。
manifest文件可分为三部分:
(1) CACHE MANIFEST - 在此标题下列出的文件将在首次下载后进行缓存
(2)NETWORK - 在此标题下列出的文件需要与服务器的连接,且不会被缓存
(3)FALLBACK - 在此标题下列出的文件规定当页面无法访问时的回退页面(比如 404 页面)
简单示例:
CACHE MANIFEST
#version 1.1 /*版本号*/
CACHE:
html/index.html /*需要缓存的文件*/
NETWORK:
js/jquery.js /*不需要缓存的文件*/
FALLBACK:
html/index.html /*当页面无法访问时的回退页面*/
3)离线缓存与传统浏览器缓存区别:
浏览器缓存(Browser Caching)是为了节约网络的资源加速浏览,浏览器在用户磁盘上对最近请求过的文档进行存储,当访问者再次请求这个页面时,浏览器就可以从本地磁盘显示文档,这样就可以加速页面的阅览
区别:
1、离线缓存是针对整个应用,浏览器缓存是单个文件
2、离线缓存断网了还是可以打开页面,浏览器缓存不行
3、离线缓存可以主动通知浏览器更新资源
5.3、本地存储和离线存储有什么不同
本地存储与离线缓存都是为了方便网页的加载,提高用户体验等。
本地存储一般存储的都是数据,而离线缓存一般存储的是网页等。
6.冒泡算法思想
交换排序的基本思想是:两两比较待排序记录的关键字,发现两个记录的次序相反时即进行交换,直到没有反序的记录为止。
应用交换排序基本思想的主要排序方法有:冒泡排序和快速排序。
7.vue中的key值作用
需要使用key来给每个节点做一个唯一标识,
Diff算法就可以正确的识别此节点,
找到正确的位置区插入新的节点。
所以一句话,key的作用主要是为了高效的更新虚拟DOM
8.v-if和v-show的差别
v-if 是动态添加,当值为 false 时,是完全移除该元素,即 dom 树中不存在该元素。
v-show 仅是隐藏 / 显示,值为 false 时,该元素依旧存在于 dom 树中。
若其原有样式设置了 display: none 则会导致其无法正常显示
9.vue的生命周期
从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、卸载等一系列过程
简单讲是一个组件从开始到最后消亡所经历的各种状态,就是一个组件的生命周期
一个vue实例在创建过程中调用的几个生命周期钩子。
1.beforeCreate 说明:在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用 注意:此时,无法获取 data中的数据、methods中的方法
2.created 这是一个常用的生命周期,可以调用methods中的方法、改变data中的数据。最常见的就是发送ajax请求来对已经构建完毕的vue对象的静态属性进行一些初始化。
3.beforeMount 在挂载开始之前被调用
4.mounted 此时,vue实例已经挂载到页面中,可以获取到el中的DOM元素,进行DOM操作
5.beforeUpdate 数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
6.updated 组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。
7.beforeDestroy 实例销毁之前调用。在这一步,实例仍然完全可用。使用场景:实例销毁之前,执行清理任务,比如:清除定时器等
8.destroyed 说明:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
10.跨域
1. 什么是跨域请求
在 HTML 中,<a>
, <form>
, <img>
, <script>
, <iframe>
, <link>
等标签以及 Ajax 都可以指向一个资源地址,而所谓的跨域请求就是指:当前发起请求的域与该请求指向的资源所在的域不同时的请求。这里的域指的是这样的一个概念:我们认为如果 “协议 + 域名 + 端口号” 均相同,那么就是同域。
举个例子:假如一个域名为 aaa.cn
的网站,它发起一个资源路径为 aaa.cn/books/getBookInfo
的 Ajax 请求,那么这个请求是同域的,因为资源路径的协议、域名以及端口号与当前域一致(例子中协议名默认为http,端口号默认为80)。但是,如果发起一个资源路径为 bbb.com/pay/purchase
的 Ajax 请求,因为请求域 http://bbb.com:80
和发起请求的域 http://aaa.cn:80
不同,那么这个请求就是跨域请求。
域名、协议、端口有一个不同就不是同源,三者均相同,这两个网站才是同源
2.跨域的解决方案
1、 通过jsonp跨域
jsonp的原理就是利用<script>
标签没有跨域限制,通过<script>
标签src属性,发送带有callback参数的GET请求,服务端将接口返回数据拼凑到callback函数中,返回给浏览器,浏览器解析执行,从而前端拿到callback函数返回的数据。只能发送get一种请求。
2、跨域资源共享(CORS)
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
3、nginx代理跨域
nginx代理跨域,实质和CORS跨域原理一样,通过配置文件设置请求响应头Access-Control-Allow-Origin…等字段。
1)nginx配置解决iconfont跨域
浏览器跨域访问js、css、img等常规静态资源被同源策略许可,但iconfont字体文件(eot|otf|ttf|woff|svg)例外,此时可在nginx的静态资源服务器中加入以下配置。
location / {
add_header Access-Control-Allow-Origin *;
}
2)nginx反向代理接口跨域
跨域问题:同源策略仅是针对浏览器的安全策略。服务器端调用HTTP接口只是使用HTTP协议,不需要同源策略,也就不存在跨域问题。
实现思路:通过Nginx配置一个代理服务器域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域访问。
4、nodejs中间件代理跨域
node中间件实现跨域代理,原理大致与nginx相同,都是通过启一个代理服务器,实现数据的转发,也可以通过设置cookieDomainRewrite参数修改响应头中cookie中域名,实现当前域的cookie写入,方便接口登录认证。
5、document.domain + iframe跨域
此方案仅限主域相同,子域不同的跨域应用场景。实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。
6、location.hash + iframe跨域
实现原理: a欲与b跨域相互通信,通过中间页c来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。
7、window.name + iframe跨域
window.name属性的独特之处:name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。
通过iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。
8、postMessage跨域
postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:
- 页面和其打开的新窗口的数据传递
- 多窗口之间消息传递
- 页面与嵌套的iframe消息传递
- 上面三个场景的跨域数据传递
9、WebSocket协议跨域
WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是server push技术的一种很好的实现。
原生WebSocket API使用起来不太方便,我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。
小结
以上就是9种常见的跨域解决方案,jsonp(只支持get请求,支持老的IE浏览器)适合加载不同域名的js、css,img等静态资源;CORS(支持所有类型的HTTP请求,但浏览器IE10以下不支持)适合做ajax各种跨域请求;Nginx代理跨域和nodejs中间件跨域原理都相似,都是搭建一个服务器,直接在服务器端请求HTTP接口,这适合前后端分离的前端项目调后端接口。document.domain+iframe适合主域名相同,子域名不同的跨域请求。postMessage、websocket都是HTML5新特性,兼容性不是很好,只适用于主流浏览器和IE10+。
11.http状态码
HTTP状态码总的分为五类:
1开头:信息状态码
2开头:成功状态码
3开头:重定向状态码
4开头:客户端错误状态码
5开头:服务端错误状态码
1XX:信息状态码
状态码 | 含义 | 描述 |
100 | 继续 | 初始的请求已经接受,请客户端继续发送剩余部分 |
101 | 切换协议 | 请求这要求服务器切换协议,服务器已确定切换 |
2XX:成功状态码
状态码 | 含义 | 描述 |
200 | 成功 | 服务器已成功处理了请求 |
201 | 已创建 | 请求成功并且服务器创建了新的资源 |
202 | 已接受 | 服务器已接受请求,但尚未处理 |
203 | 非授权信息 | 服务器已成功处理请求,但返回的信息可能来自另一个来源 |
204 | 无内容 | 服务器成功处理了请求,但没有返回任何内容 |
205 | 重置内容 | 服务器处理成功,用户终端应重置文档视图 |
206 | 部分内容 | 服务器成功处理了部分GET请求 |
3XX:重定向状态码
状态码 | 含义 | 描述 |
300 | 多种选择 | 针对请求,服务器可执行多种操作 |
301 | 永久移动 | 请求的页面已永久跳转到新的url |
302 | 临时移动 | 服务器目前从不同位置的网页响应请求,但请求仍继续使用原有位置来进行以后的请求 |
303 | 查看其他位置 | 请求者应当对不同的位置使用单独的GET请求来检索响应时,服务器返回此代码 |
304 | 未修改 | 自从上次请求后,请求的网页未修改过 |
305 | 使用代理 | 请求者只能使用代理访问请求的网页 |
307 | 临时重定向 | 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求 |
4XX:客户端错误状态码
状态码 | 含义 | 描述 |
400 | 错误请求 | 服务器不理解请求的语法 |
401 | 未授权 | 请求要求用户的身份演验证 |
403 | 禁止 | 服务器拒绝请求 |
404 | 未找到 | 服务器找不到请求的页面 |
405 | 方法禁用 | 禁用请求中指定的方法 |
406 | 不接受 | 无法使用请求的内容特性响应请求的页面 |
407 | 需要代理授权 | 请求需要代理的身份认证 |
408 | 请求超时 | 服务器等候请求时发生超时 |
409 | 冲突 | 服务器在完成请求时发生冲突 |
410 | 已删除 | 客户端请求的资源已经不存在 |
411 | 需要有效长度 | 服务器不接受不含有效长度表头字段的请求 |
412 | 未满足前提条件 | 服务器未满足请求者在请求中设置的其中一个前提条件 |
413 | 请求实体过大 | 由于请求实体过大,服务器无法处理,因此拒绝请求 |
414 | 请求url过长 | 请求的url过长,服务器无法处理 |
415 | 不支持格式 | 服务器无法处理请求中附带媒体格式 |
416 | 范围无效 | 客户端请求的范围无效 |
417 | 未满足期望 | 服务器无法满足请求表头字段要求 |
5XX:服务端错误状态码
状态码 | 含义 | 描述 |
500 | 服务器错误 | 服务器内部错误,无法完成请求 |
501 | 尚未实施 | 服务器不具备完成请求的功能 |
502 | 错误网关 | 服务器作为网关或代理出现错误 |
503 | 服务不可用 | 服务器目前无法使用 |
504 | 网关超时 | 网关或代理服务器,未及时获取请求 |
505 | 不支持版本 | 服务器不支持请求中使用的HTTP协议版本 |
12.MVVM模式
MVVM 由 Model、View、ViewModel 三部分构成,Model 层代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑;View 代表UI 组件,它负责将数据模型转化成UI 展现出来,ViewModel 是一个同步View 和 Model的对象。
在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。
ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。
13.深拷贝和浅拷贝
(1)什么是深拷贝、浅拷贝
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。修改新对象会改到原对象。
深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
(2)浅拷贝实现方式
Object.assign()
Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。
Object.assign 方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象上。
如下代码演示:
var target = {a: 0}; var source1 = {b: 1}; var source2 = {c: 2}; Object.assign(target, source1, source2); console.log(target); // 输出 {a: 0, b: 1, c: 2}
展开运算符...
展开运算符是一个 es6 / es2015特性,它提供了一种非常方便的方式来执行浅拷贝,这与 Object.assign ()的功能相同。
let obj1 = { name: 'Kobe', address:{x:100,y:100}}
let obj2= {... obj1}
obj1.address.x = 200;
obj1.name = 'wade'
console.log('obj2',obj2) // obj2 { name: 'Kobe', address: { x: 200, y: 100 } }
concat()
let arr = [1, 3, {
username: 'kobe'
}];
let arr2 = arr.concat();
arr2[2].username = 'wade';
console.log(arr); //[ 1, 3, { username: 'wade' } ]
slice()
slice() 方法可提取字符串的某个部分,并以新的字符串返回被提取的部分。
stringObject.slice(start,end)
let arr = [1, 3, {
username: ' kobe'
}];
let arr3 = arr.slice();
arr3[2].username = 'wade'
console.log(arr); // [ 1, 3, { username: 'wade' } ]
(3)深拷贝的实现方式
1.JSON.parse(JSON.stringify())
这也是利用JSON.stringify将对象转成JSON字符串,再用JSON.parse把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。
let arr = [1, 3, {
username: ' kobe'
}];
let arr4 = JSON.parse(JSON.stringify(arr));
arr4[2].username = 'duncan';
console.log(arr, arr4)
(4)深拷贝的弊端
(1)会忽略 `undefined`
(2)会忽略 `symbol`
(3)不能序列化函数
(4)不能解决循环引用的对象
(5)不能正确处理`new Date()`
(6)不能处理正则
其中(1)(2)(3) `undefined`、`symbol` 和函数这三种情况,会直接忽略。
// saucxs
let obj = {
name: 'saucxs',
a: undefined,
b: Symbol('saucxs'),
c: function() {}
}
console.log(obj);
// {
// name: "saucxs",
// a: undefined,
// b: Symbol(saucxs),
// c: ƒ ()
// }
let b = JSON.parse(JSON.stringify(obj));
console.log(b);
// {name: "saucxs"}
其中(4)循环引用会报错
// saucxs
let obj = {
a: 1,
b: {
c: 2,
d: 3
}
}
obj.a = obj.b;
obj.b.c = obj.a;
let b = JSON.parse(JSON.stringify(obj));
// Uncaught TypeError: Converting circular structure to JSON
其中(5)* `new Date` 情况下,转换结果不正确。
// saucxs
new Date();
// Mon Dec 24 2018 10:59:14 GMT+0800 (China Standard Time)
JSON.stringify(new Date());
// ""2018-12-24T02:59:25.776Z""
JSON.parse(JSON.stringify(new Date()));
// "2018-12-24T02:59:41.523Z"
解决方法转成字符串或者时间戳就好了。
// saucxs
let date = (new Date()).valueOf();
// 1545620645915
JSON.stringify(date);
// "1545620673267"
JSON.parse(JSON.stringify(date));
// 1545620658688
其中(6)正则情况下
// saucxs
let obj = {
name: "saucxs",
a: /'123'/
}
console.log(obj);
// {name: "saucxs", a: /'123'/}
let b = JSON.parse(JSON.stringify(obj));
console.log(b);
// {name: "saucxs", a: {}}
(5)赋值与浅拷贝和深拷贝的区别
和原数据是否指向同一对象 | 第一层数据为基本数据类型 | 原数据中包含子对象 | |
赋值 | 是 | 改变会使原数据一起改变 | 改变会使原数据一起改变 |
浅拷贝 | 否 | 改变不会使原数据一起改变 | 改变会使原数据一起改变 |
深拷贝 | 否 | 改变不会使原数据一起改变 | 改变不会使原数据一起改变 |
14.promise
Promise 是异步编程的一种解决方案,
15.ES6有哪些新特性
(1)let和const
let是块级作用域。不存在变量提升。不允许重复声明
const声明常量,在声明时必须被赋值。块级作用域。不存在变量提升。不允许重复声明。
(2)模板字符串
模板字符串主要用于方便将字符串和变量连接起来,用反引号` `,${}
反引号中放字符串和${],${}括号内写入需要的引用的变量。
(3)箭头函数
1.基础语法
通常函数的定义方法
var fn1 = function(a, b) {
return a + b
}
function fn2(a, b) {
return a + b
}
使用ES6箭头函数语法定义函数,将原函数的“function”关键字和函数名都删掉,并使用“=>”连接参数列表和函数体。
var fn1 = (a, b) => {
return a + b
}
(a, b) => {
return a + b
}
2.箭头函数基本特点
(1). 箭头函数this为父作用域的this,不是调用时的this
箭头函数的this永远指向其父作用域,任何方法都改变不了,包括call,apply,bind。
普通函数的this指向调用它的那个对象
(2)箭头函数不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
(3)箭头函数如果返回值是一个对象,一定要加()
普通:
const show = () => {
}
返回值为对象:
const show = () => ({
})
(4)当函数参数只有一个,括号可以省略;但是没有参数时,括号不可以省略。
// 无参
var fn1 = () => {}
// 单个参数
var fn2 = a => {}
// 多个参数
var fn3 = (a, b) => {}
// 可变参数
var fn4 = (a, b, ...args) => {}
(4)数组,对象解构赋值
ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值;
// 1、数组的解构赋值
const F4 = ["大哥", "二哥", "三哥", "四哥"];
let [a, b, c, d] = F4;
// 这就相当于我们声明4个变量a,b,c,d,其值分别对应"大哥","二哥","三哥","四哥"
console.log(a + b + c + d); // 大哥二哥三哥四哥
// 2、对象的解构赋值
const F3 = {
name: "大哥",
age: 22,
sex: "男",
xiaopin: function () { // 常用
console.log("我会演小品!");
}
}
let {
name,
age,
sex,
xiaopin
} = F3; // 注意解构对象这里用的是{}
console.log(name + age + sex + xiaopin); // 大哥22男
xiaopin(); // 此方法可以正常调用
//好像只是一个指向
console.log(name===F3.name);//true
console.log(xiaopin===F3.xiaopin);//true
(5)ES6中函数参数的默认值
ES6 允许给函数参数赋值初始值
/1. 形参初始值 具有默认值的参数, 一般位置要靠后(潜规则)
function add(a, b, c = 10) {
return a + b + c;
}
(6)扩展运算符
扩展运算符( spread )是三个点(...)将一个数组转为用逗号分隔的参数序列。
基本用法:
1.拆解字符串与数组
var array = [1,2,3,4];
console.log(...array);//1 2 3 4
var str = "String";
console.log(...str);//S t r i n g
2.合并数组
var arr1 = ['a', 'b'];
var arr2 = ['c'];
[...arr1, ...arr2]
// [ 'a', 'b', 'c']
3.扩展运算符可以与解构赋值结合起来,用于生成数组。
(如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错)
4,函数的返回值
JavaScript 的函数只能返回一个值,如果需要返回多个值,只能返回数组或对象。扩展运算符提供了解决这个问题的一种变通方法。
var dateFields = readDateFields(database);
var d = new Date(...dateFields);
5.可以将字符串转为真正的数组。
[...'hello']
// [ "h", "e", "l", "l", "o" ]
(7)Symbol 原始数据类型
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是JavaScript 语言的·第七种数据类型·
1.Symbol 特点
- Symbol 的值是唯一的,用来解决命名冲突的问题;
- Symbol 值不能与其他数据进行运算;
- Symbol定义的对象属性不能使用for…in循环遍历 ,但是可以使用Reflect.ownKeys 来获取对象的所有键名;
创建symbol
变量最简单的方法是用Symbol()
函数。
每个Symbol实例都是唯一的。因此,当你比较两个Symbol实例的时候,将总会返回false
:
const symbol1 = Symbol();
const symbol2 = Symbol();
symbol1 === symbol2; // false
2.symbol
应用场景
1. 当有重名的情况,解决命名冲突的问题
使用Symbol,Symbol声明的值是独一无二的,在内存中处于不同的地址 :
const stu1 = Symbol('李四')
const stu2 = Symbol('李四')
const grade = {
[stu1]: {address: 'yyy', tel: '222'},
[stu2]: {address: 'zzz', tel: '333'},
}
console.log(grade)
//李四: {address: "yyy", tel: "222"}
//李四: {address: "zzz", tel: "333"}
// 获取具体某一个重名的人的信息
console.log(grade[stu1])
//{address: 'yyy', tel: '222'}
2.将属性保护起来
const sym = Symbol('KD')
class User {
constructor(name) {
this.name = name
this[sym] = 'KDKD'
}
getName() {
return this.name + this[sym]
}
}
const user = new User('Dorothy')
console.log(user.getName())
// DorothyKDKD
//Reflect.ownKeys可以获取全部属性值
for(let key of Reflect.ownKeys(user)){
console.log(key)
// name Symbol(KD)
}
16.什么是防抖和节流?有什么区别?
防抖:触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间;每次触发事件时都取消之前的延时调用方法
function debounce(fn) {
let timeout = null; // 创建一个标记用来存放定时器的返回值
return function () {
clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉
timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数
fn.apply(this, arguments);
}, 500);
};
}
function sayHi() {
console.log('防抖成功');
}
var inp = document.getElementById('inp');
inp.addEventListener('input', debounce(sayHi)); // 防抖
节流:高频事件触发,但在 n 秒内只会执行一次,所以节流会稀释函数的执行频率。每次触发事件时都判断当前是否有等待执行的延时函数。
防抖和节流区别:防抖只会触发最后一次事件,节流只有请求成功发生响应后才会触发下一次事件
17.http和https的区别?
HTTP (HyperText Transfer Protocol),即超文本运输协议,是实现网络通信的一种规范。
HTTP协议运行在TCP之上。所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份
HTTP的连接很简单,是无状态的;
HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比HTTP协议安全。所有传输的内容都经过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。此外客户端可以验证服务器端的身份,如果配置了客户端验证,服务器方也可以验证客户端的身份
18.说几条web前端优化策略
前端性能优化分为两类:一类是文件加载更快、另一类是文件渲染更快。
一、文件加载更快
1. 让传输的数据包更小(压缩文件/图片)
2. 减少网络请求的次数:雪碧图/精灵图、节流防抖
3. 减少渲染的次数:缓存(HTTP缓存、本地缓存、Vue的keep-alive缓存等)
二、文件渲染更快
1. 提前渲染:ssr服务器端渲染
2. 避免渲染阻塞:CSS放在HTML的head中 JS放在HTML的body底部
3. 避免无用渲染:懒加载
4. 减少渲染次数:对dom查询进行缓存、将dom操作合并、使用减少重排的标签
加分回答
1. 雪碧图的应用场景一般是项目中不常更换的一些固定图标组合在一起,比如logo、搜索图标、切换图标等。
2. 电商项目中最常用到的懒加载,一般在查看商品展示的时候通常下拉加载更多,因为商品数据太多,一次性请求过来数据太大且渲染的时间太长。