数组降维的几种方法
使用递归降维
先声明一个空数组,再声明一个函数,把要降维的数组作为参数传进去,函数体内遍历要降维的数组,判断数组中的元素是否是数组,是的话就再调用这个函数把当前元素作为参数传入,不是直接添加到声明的空数组中
将多维数组转化为字符串,再转换成一维数组
使用数组方法flat()
使用Infinity作为深度,展开任意深度的嵌套数组)
使用concat方法
利用扩展运算符
对象深度克隆
const newObj = {};
const clone = (newObj, oldObj) => {
for (k in oldObj) {
if (oldObj[k] instanceof Array) {
newObj[k] = [];
clone(newObj[k], oldObj[k]);
} else if (oldObj[k] instanceof Object) {
newObj[k] = {};
clone(newObj[k], oldObj[k]);
} else {
newObj[k] = oldObj[k];
}
}
}
clone(newObj,oldObj)
数组去重
1.循环 + indexOf方法 / findIndex方法
indexOf方法:返回数组中第一次出现给定元素的下标,没有则返回-1,用法 数组.indexOf('给定元素')
findIndex方法:返回数组中第一个符合条件的元素的下标,没有则返回-1
let arr = [1, 2, 3,4 ,5,6, 4, 3, 8, 1]
let newArr = []
arr.forEach(c =>{
newArr.indexOf(c) === -1? newArr.push(c):newArr
})
arr.forEach(c =>{
newArr.findIndex(c1 => c === c1) === -1? newArr.push(c):newArr
})
console.log(newArr) //[1,2,3,4,5,6,8]
2.利用sort()方法
const arr = [1, 2, 3, 4, 5, 6, 4, 3, 8, 1]
arr.sort()
arr.forEach((c,i) =>{
arr[i] === arr[i - 1] ? arr.splice(i,1) :arr
})
console.log(arr) //[1,2,3,4,5,6,8]
3.Set()构造函数
Set():Set构造函数可以创建Set对象,可以存储任意类型的唯一值(基础类型和引用类型都可以)
const arr = [1, 2, 3, 4, 5, 6, 4, 3, 8, 1]
const newArr = [...new Set(arr)]
console.log(newArr) //[1,2,3,4,5,6,8]
new Set()方法返回的是一个类数组,也可以结合Array.form() 转成真实数组
const arr = [1, 2, 3, 4, 5, 6, 4, 3, 8, 1]
const newArr = Array.from(new Set(arr))
console.log(newArr) //[1,2,3,4,5,6,8]
4.利用inclueds方法
const arr = [1, 2, 3, 4, 5, 6, 4, 3, 8, 1]
const newArr = []
arr.forEach(c =>{
newArr.includes(c)? newArr : newArr.push(c)
})
console.log(newArr) //[1,2,3,4,5,6,8]
常见的http状态码及代表的含义
//1.信息代码:1xx:信息,请求收到,继续处理;
//2.成功代码:2xx:成功,行为被成功地接受、理解和采纳;
//3.重定向:3xx:重定向,为了完成请求,必须进一步执行的动作;
//4.客户端错误:4xx:客户端错误,请求包含语法错误或者请求无法实现;
//5.服务器错误:5xx:服务器错误,服务器不能实现一种明显无效的请求;
//200(ok):请求成功,请求所希望的响应头或数据体将随此响应返回
//304:指示资源未发生改变,客户端可以使用缓存版本
//400(Bad Request):请求格式错误(请求携带的参数不正确)
//401:未认证,没有登录;token过期
//403:没有访问权限
//404(Not Found):请求失败,服务器无法正常提供信息,或是服务器无法回应,且不知道原因返回的页面
//500(Internal Server Error):基本是服务器出现错误会返回的状态
//502:网关错误
//503:请求超时或停机维护
localStorage、sessionStorage、cookie的区别
共同点:都是保存在浏览器且同源的
区别:
1.cookie数据会在同源的http请求中携带;sessionStorage和localStorage不会自动把数据发送给服务器,仅保存在本地
2.cookie数据的存储大小不超过4k,sessionStorage和localStorage的存储数据是5M
3.sessionStorage仅在当前浏览器窗口关闭之前有效,localStorage是始终有效,cookie是在设置的过期时间内有效
4.sessionStorage在不同的浏览器窗口数据不能共享,即使是同一个页面;localStorage和cookie在所有的同源窗口都是共享的
一个页面从输入URL到页面 加载显示完成,这个过程中都发 生了什么
1.URL解析:地址栏输入地址,浏览器对输入的内容进行解析,判断URL的合法性、是否有可用的缓存
2.DNS解析:浏览器查找对应的IP地址
3.建立TCP连接(三次握手):浏览器向服务器发起TCP连接,与浏览器建立TCP三次握手
4.HTTP请求:浏览器将http请求数据发送给服务器(客户端->服务器)
5.HTTP响应:服务器处理接收到的请求,返回响应结果给浏览器(服务器->浏览器)
6.关闭TCP连接(四次挥手):数据传输完成后,经过四次握手终止连接
7.页面渲染:浏览器解析响应的结果,进行页面渲染
HTTP缓存机制
本地缓存基于本地环境的内存,访问速度快,对于一些变更率低、实时性要求低的数据可以放在本地缓存中,提升访问速度;使用本地缓存能够减少和redis类的远程缓存间的数据交互,减少网络I/O开销,降低这一过程中在网络通信上的耗时
为什么要使用http缓存:优化性能,提升访问速度,减少请求次数
强缓存:不向服务器发起请求,浏览器要获取特定的数据时,会先检查本地的缓存是否存在该数据,如果存在就直接在本地获取,如果不存在就向服务器索要数据
协商缓存:浏览器第一次请求数据时,服务器将缓存标识与数据一起返回给客户端,客户端将二者备份到缓存数据库中,再次请求数据时,客户端将备份的缓存标识发送给服务器,服务器根据缓存标识进行判断,判断成功后返回304状态码通知客户端比较成功可以使用缓存数据
es5和es6的区别,es6的新增内容
es6相对于es5更加简洁,提高了开发效率,新增了一些新特性
es6新增:
1.let和const:let声明变量,const声明常量,let和const不存在变量提升,let和const声明有块级作用域,只能在块级作用域内访问
2.symbol:一种新的基本数据类型,表示一个独一无二的值,不能与其他数据类型进行运算
3.模板字符串:(`xxx${变量}`) 字符串的新方法:includes
4.对象/数组解构:const {a,b} = {a:1,b:2} const [a,b,c] = [1,2,3]
console.log(a,b) // 1,2 console.log(a,b,c) // 1,2,3
5.Set() 构造函数:Set对象是值的集合,允许存储任何类型的唯一值
6.数组的新方法:
Array.from:将伪数组转换成真数组
includes:判断数组中是否包含一个指定的值
map:通常用来遍历迭代加工数组
forEach:通常用来遍历数组
filter:筛选出数组中符合条件的所有元素返回到一个新的数组中
find:返回数组中符合条件的第一个元素
some:数组中有一项元素符合判断条件就返回true,只有所有元素都不符合条件才返回false
every:数组中所有元素都符合判断条件才返回true,只要有一个不符合就返回false
7.Object对象的新方法
object.is():判断两个值是否指向同一内存地址
object.assign():用于将所有可枚举属性的值从一个或多个源对象分配到目标对象
object.keys():
object.values():
object.entries():
8.对象声明简写
let person={
name,
age
}
9. ...拓展运算符(对象拓展符)
10.箭头函数
11.模块化
12.promise
let、const、var的区别
1.var声明变量存在变量提升,let和const不存在变量提升
2.let和const声明有块级作用域,只能在块级作用域中访问
3.同一作用域下let和const不能声明同名变量,var可以
4.const定义常量不能修改,但定义的是对象时,对象的属性值可以改变
vue数据双向绑定的原理
vue数据的双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的
通过object.defineProperty()方法设置set和get函数来实现数据的劫持,在数据变化时触发相应的监听回调,也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化数据也随之发生改变
Object.defineProperty 和 Proxy 的区别
object.defineProperty(obj,prop,descriptor)方法 有三个参数:
obj:要定义属性的对象
prop:要定义或修改的属性
descriptor:具体的改变方法
用这个方法来定义一个值,调用时我们是使用了它里面的get方法;当给这个属性赋值时是调用了它里面的set()方法
proxy对象用于定义基本操作的自定义行为。
const p = new Proxy(target, handler)
target: 要使用 Proxy 包装的目标对象
handler: 一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为
父子组件传值(父子通信)
父传子:
在父组件的子组件标签上绑定属性,将数据传递给子组件;子组件中通过props接收数据使用
子传父:
子组件中定义事件,通过$emit发送给父组件,父组件在子组件标签上通过(@自定义事件名)接收事件
this.$emit('自定义事件名',参数1,参数2,...)
vue实现组件缓存
<keep-alive>包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染
activated钩子函数:
在组件第一次渲染时会被调用,之后在每次组件被激活时调用
deactivatde钩子函数:
组件被停用时(离开路由)被调用
v-show和v-if
相同点:都能控制元素的显示与隐藏
不同点:
1.v-show是给绑定的DOM元素添加CSS样式display:none控制显隐,DOM元素仍然存在; v-if是将DOM元素直接删除,DOM 元素不再存在。
2.v-if是惰性的,在初始判断条件为false时,初次不会渲染,v-show不管初始条件是什么都会渲染;v-if在显隐切换过程中 合适地销毁和重建内部的事件监听和子组件
3.v-if由false变为true时,会触发组件的beforeCreate、created、beforeMount、mounted钩子,由true变为false时会 触发组件的 beforeDestory、destoryed钩子;v-show的显隐不会触发组件的生命周期钩子
4.v-show 的初始渲染消耗高, v-if 的切换消耗更高。
v-if和v-show的使用场景
需要非常频繁的切换时,使用v-show
在运行时条件很少改变,则使用v-if较好。
为什么避免v-if和v-for一起使用
因为v-for的优先级时高于v-if的,如果作用在同一元素上,输出的渲染函数中可以看出会先执行循环再判断条件,每次重渲染的时候遍 历整个列表,会造成性能的浪费。
v-for比v-if优先,即每一次都需要遍历整个数组,影响速度;
更好的解决方案: 是用computed先获取符合条件的数据,再进行遍历
watch、computed和methods的区别
watch用于监听指定数据的变化并执行响应操作
computed用于定义计算属性,它会根据依赖的数据自动更新计算结果
methods用于定义方法,在需要时手动调用执行
在数据变化时执行异步或开销较大的操作,可以使用watch
需要依赖其他响应式数据进行计算,且希望有缓存机制,可以使用computed
需要在模板中触发事件或执行逻辑操作,可以使用methods
vue中key值的作用
用来给每一个节点做唯一标识的属性,它的作用是帮助vue进行DOM元素的复用;当vue更新DOM时,它会基于新数据生成虚拟DOM 树,将其与旧的DOM树进行对比,通过对比找到需要更新的节点,达到更新视图的目的,在进行对比时,vue会根据key值来判断新旧 节点是否相同来决定是否进行复用。
当状态数据发生变化时,vue会根据【新数据】生成【新的虚拟dom】
随后vue进行【新的虚拟dom】与【旧的虚拟dom】的diff比较 比较规则如下:
a. 如果旧虚拟dom找到了与新虚拟dom相同的key
(1)若旧虚拟dom中内容没变,直接使用之前的真实dom
(2)若旧虚拟dom中内容发生了改变,则生成新的真实dom 随后替换掉页面中的真实dom
b. 如果旧虚拟dom未找到与新虚拟dom相同的key
根据数据创建新的真实dom随后渲染到页面