// 判断数组对象特定属性是否相同
function isEqualObj(arr, key) {
const newArr = arr.map(item => item[key])
const arrSet = new Set(newArr)
return arrSet.size !== newArr.length
}
// js 继承有四种 原型链继承, 构造函数继承, 组合继承,寄生继承
// 原型继承,改了其中一个实例会影响其它的,构造函数继承不到父类的属性和方法
//组合继承
function chidren(name) {
this.name = name
}
chidren.prototype.getName = function() {
return this.name
}
function inhert() {
// 构造函数继承
chidren.call(this,'王二')
}
inhert.prototype = new chidren()
// inhert.prototype = Object.create(chidren.prototype) //将指向父类实例改为指向父类原型 为寄生继承
inhert.prototype.constructor = inhert
// 使用
const inhert1 = new inhert()
inhert1.name // ['王二']
// 数组去重
function removeDuplicate(arr, key) {
let obj = {}
const curArr = arr.reduce((pre, cur)=> {
obj[pre[key]] ? '' : obj[pre[key]] = true && pre.push(cur)
return pre
},[])
return curArr
}
// 实现sleep(1000)
const sleep = time => {
return new Promise((resolve) => {
resolve(setTimeout(() => {
console.log('time');
}, time))
})
}
// 使用
sleep(1000).then(res => {
console.log(res);
})
// 手动实现bind
Function.prototype.myBind = function() { // 不能使用箭头函数,应为this的指向不同
// arguments 可以获取函数的所有参数,是一个伪数组, 使用Array.from() 将 伪数组转换成数组
const arg = Array.from(arguments)
// 获取this 指向取出数组的第一项,数组剩余的就是传递的参数
const self = this
return () => {
return self.apply(_this,arg)
}
}
// 使用
function fn1(a, b, c) {
console.log('this',this);
console.log(a,b,c);
}
const fn2 = fn1.myBind(10,20,30)
console.log(fn2);
// 手动实现call
Function.prototype.myCall = function() {
const fn = Symbol('fn') // 声明一个独有的symbol属性,防止fn覆盖已有属性
thisArg = thisArg || window // 如没有传入this,默认绑定到window
thisArg[fn] = this // this 指向调用call的对象,即我们要改变this指向的函数
const result = thisArg[fn](...args) // 指向当前函数
delete thisArg[fn] // 删除声明的fn属性
return result
}
// 并集,交集,差集
let set1 = new Set([1,2,3])
let set2 = new Set([2,3,4])
// 并集
let union = new Set([...set1, ...set2])
// 交集
let interset = new Set([...set1].filter(x => set2.has(x)))
// 差集
let difference = new Set([...set1].filter(x=> !set2.has(x)))
// 克隆
function deepClone(obj) {
if (!obj || typeof obj !== 'object') return
const data = Array.isArray(obj) ? [] : {}
for (let i in obj) {
data[i] = typeof(obj[i]) === 'object' ? deepClone(obj[i]) : obj[i]
}
return data
}
// 去重
function removeRepeat(arr, key) {
let obj = {}
const cur = arr.reduce((pre,cur) => {
obj[cur[key]] ? '' : obj[cur[key]] = true && pre.push(cur)
return pre
},[])
return cur
}
// 求和
function sum(arr) {
let data = arr.reduce((pre,cur) => {
return pre + cur
},0)
}
// 防抖是在事件触发后n秒再去执行回调,如果n秒内再次被触发,则重新计算,最常用 搜锁框输入查询,表单提交
function debouce(fn, wait) {
let time = null
return function() {
time && clearTimeout(time)
time = setTimeout(() => {
fn.apply(this, arguments)
}, wait);
}
}
// 节流 是指如果频繁触发一个事件,则n秒后执行一次
function throttle(fn, wait) {
let flag = true
return function() {
if (!flag) return
flag = false
setTimeout(() => {
fn.apply(this, arguments)
flag = true
}, wait);
}
}
// 计算 1+2+3...100
function sumByValue(val) {
if (val === 1) return
return sumByValue(val -1) + val
}
// Set 和Map的区别是,Set类似于数组,每一个值是唯一的,Map类似于对象,是键值对的集合
// AMD require 是运行时调用,可以用在任何地方,是赋值的过程可以是数组,对象,字符串
// CMD import 是编译是调用,所以必须用于开头,是解构的过程
// 通常缓存,分为协商缓存和强制缓存
// 强制缓存: 1.浏览器控制 2.后端把过期时间和资源发过来,浏览器每次获取资源看一下过期时间到了没
// 协商缓存: 1.服务器控制 2.后端把资源标识,和资源发送过来,浏览器每次用的时候,就会拿标识和后端存储的对比一下不一样就更新
// 强制缓存使用时间来判断,时间分为相对时间和绝对时间
// 绝对时间 expires字段
// 相对时间 后端给有效时长,浏览器自己倒计时,对应着请求的cach-control字段,同时存在。cach-control优先级更高
// js垃圾回收,就是标记清除和引用计数
// js中 ! 和 !! !将变量转换成boolen类型,!!常常用来做类型判断,在第一步!之后再做逻辑取反运算, ??只有在左侧为null和undefiend时,才会返回右侧数据
// 渐进式图片加载 antimoderate
// aligin-self: baseline
// vue中定义props类型,Proptype
// [1,2,3].map(parseInt) 结果时[1,NAN,NAN] 原因是,最终会转换成 arr.map((value,index, array) => parseInt(value,index))
// flex:1 对应这flex-grow(拉伸占比) flex-shrink(收缩规则,0 为不收缩) flex-basis(主轴方向初始大小)
// 回流,当元素尺寸,位置发生变化需要重新计算。 重绘: 当元素DOM样式发生变化,没有影响到DOM的几何尺寸
// GET和POST 请求的区别: 1. get请求在url上,post在请求体中 2.get请求有长度限制(浏览器限制的) 3.post请求相对安全点,get请求在url上,且有历史记录 4. get请求能缓存,post不能
// HTTPS使用443端口,HTTP使用80端口 2. http是超文本传输协议,是明文传输,https是经过SSL加密协议,传输更安全,不过要申请证书 3. https比http慢因为,除了tcp握手的三个包,还有ssl加密的9个包
// http1.1和http2.0区别: 1.1使用基于文本的格式传输,2.0使用二进制传输, 1.1不支持header数据压缩,2.0使用hpack算法对header进行数据压缩,体积更小,传输更快
// http 请求状态码总结
// 1** 服务器接收请求,需要请求者接着操作
// 2** 请求成功
// 3** 重定向,需要进一步操作
// 4** 客户端错误,请求包含语法错误,无法完成请求
// 5** 服务器错误
// 从浏览器输入url页面发生了什么?
// 1. DNS查询,解析url中对应的ip地址 2.tcp链接 3.发送http请求 4.server处理http请求,并返回http保文 5. 浏览器解析,render页面 6. http断开链接
// VUE中diff算法:
// VUE根据真实dom生成一个virtural DOM ,当virtral DOM 的某个节点数据改变后会生成一个新的Vnode,然后Vnode和 oldVnode做对比,发现不一样就直接更新dom,然后oldVnode的职位Vnode,
// 来实现节点更新。 具体是: 1.同级比较再比较字节点 2. 先判断一方是否有子节点,如果新的的没有子节点,就将旧的字节点移除掉 3.都有子节点的情况,递归比较子节点
// VUE中key的作用,尽可能的复用dom元素,新旧节点如果只有顺序不同,最佳是通过移动位置达到更新目的,需要再节点保持映射关系,key就是节点中的唯一标识
// VUE中template的编译原理 1. 将模板字符串转换成element Asts解析器 2. 对ast进行静态节点标记,主要用来虚拟dom的优化 3.使用element ast生成render函数代码字符串
// nextTick 是更新执行完成之后的回调,主要是宏任务和微任务,根据不同的情况,采用 promise MutationServer 微任务 promise 都不用就使用setTimeout
// .stop禁止事件冒泡, .prevert 阻止默认事件, .self 只有点击元素本身才会执行 .capture事件触发,会先执行大盒子的事件再执行小盒子的事件,.once只触发一次
// data为什么是一个函数,对象再栈中存放的都是对象的地址,函数的作用,就是属性私有化,保证组件修改自身的属性不会影响到其它组件
// VUE中keep-alive实现原理和缓存策略:
// 1.获取keep-alive的第一个组件 2. 根据include和 exclude名单进行匹配,决定是否缓存,不匹配直接返回组件实例,匹配进行第3步 3. 根据组件id和tag生成缓存组件的key,再去判断cache中是否存在这个key,如果存在,则用缓存的实例代替Vnode的
// 的实例,然后更新key再keys的位置(LRU置换策略),如果没有命中就缓存起来,如果超出最大缓存数,就删除cache中的第一项 4. keep-alive是一个抽象组件:自身不会渲染DOM元素,也不会出现再父组件链中 5.LRU算法:根据
// 数据的历史访问记录来进行数据淘汰,其实就是访问过的,以后访问率会高 6. LRU实现,新数据插入链表头部,每当缓存命中,则将数据移至链表头部,当链表满的时候,则将链表尾部数据丢弃
// vue-router的实现原理:单页应用只有一个页面,所有的页面切换,其实是组件之间的显示和隐藏,所有的页面都只在一个html页面上,
// vue-router是通过对window.location.hash和windown.history进行封装,来实现hash或url变化映射组件的变化
// vue-router 前端路由的核心就是改变视图的同时不会向后端发送请求,而是加载对应的而组件, 有两种模式 hash和history。 hash模式在url后面带有#,hash值会出现在#后面,但是不包含在http请求中,hash改变会
// 触发hashChage事件,能控制浏览器的前进后退,兼容性好 缺点是: 包好#不美观, 设置的值必须与原来的值不一样才会触发hashChange, 每次url改变不属于一次http请求,不利于seo优化
// history 基于pushState()和replaceState()来实现改变页面路径,histoty是浏览器提供的历史记录接口,可以通过back go forward读取历史记录,history模式下,需要后端配置相应的路径,不然会出现404
// for of 无法遍历对象,forEach和map都只能遍历数组,不能终端,前者没有返回值,后者有
// JS中 宏任务一般包含 scpirt setTimeout setInterval 微任务: promise preocess.nextTick , promise 是同步任务 then是异步任务
// 什么是事件循环: js是单线程语言,同个时间执行一件事(同步),但它可以有一个异步队列,遇到异步操作,(如axios这种阻塞时间久的),把它放到异步队列中,并继续往下执行,当同步任务执行
// 完成,就会去异步队列中找刚刚存放的事件依次执行(异步任务包含宏任务和微任务,微任务优先于宏任务)
// VUE3自定义v-model
// 父组件中使用
<test v-model:title ="value" />
//子组件中定义
<div :title="title" @update:title="title = $event">{{title}}</div>
emit('update:title',t.value)
// vue2自定义v-model
mode: {
event: 'change',
prop: 'check'
}
// rem相对于根元素 如果font-size = 16px,那
// 监听屏幕大小
window.onresize = function() {
// 获取屏幕宽度
let w = document.documentElement.clientWidth || document.body.clientWidth
// 根据设计图设置大小
HTML.style.fontSize = 16 * (w / 750) + 'px'
}
// iphonex 适配当viewport-fit = contain 时,env() 是不起作用的 必须配合 viewport-fit-cover
// env() 和 constant() 需要同时存在,且顺序不能换
paading - bottom: containsPoint(safe - area -inset -bottom);
paading - bottom: event(safe -area -inset - bottom)