闭包:
闭包是指有权访问另外一个函数作用域中的变量的函数.可以理解为(能够读取其他函数内部变量的函数)
闭包的作用: 正常函数执行完毕后,里面声明的变量被垃圾回收处理掉,但是闭包可以让作用域里的 变量,在函数执行完之后依旧保持没有被垃圾回收处理掉
闭包的形成:内部函数与周围自由变量(外部函数里面的变量)形成引用关系,就形成闭包
内存泄漏场景、如何监控以及分析
BFC
原型原型链:
https://blog.csdn.net/m0_71981318/article/details/125279739
https://juejin.cn/post/7018355953955241997
https://juejin.cn/post/6984678359275929637#heading-7
https://juejin.cn/post/6844903749345886216
js6种继承方式
js事件触发机制
js深拷贝与循环引用
数据结构
手写promise
all:全部成功-返回的就是成功的数组(数组每一项是返回的结果,数组按照all里面的顺序排列,但是all里面的执行顺序并非按照顺序执行) ---------------要是有一项失败(reject)如果没catch拦截报错,就只返回失败的这一项结果,如果这一项报错用catch拦截了 ,那后面的promise请求就还会以此返回 返回的是结果数组,reject的那一项会返回underfined
race:不管成功失败,只按照哪个快 返回哪个的结果
let p = new Promise((resolve, reject) => {
//做一些异步操作
setTimeout(() => {
console.log("执行完成1");
reject("我是成功111!!");
});
},1000);
let p1 = new Promise((resolve, reject) => {
//做一些异步操作
setTimeout(() => {
console.log("执行完成2");
reject("我是成功222!!");
});
},2000);
let p2 = new Promise((resolve, reject) => {
//做一些异步操作
setTimeout(() => {
console.log("执行完成3");
resolve("我是成功333!!");
});
},3000);
let pAll = Promise.race([p, p1, p2])
pAll.then((res)=>{
// 三个都成功则成功
console.log("-----res",res,pAll)
}, (err)=>{
// 只要有失败,则失败
console.log("-----err",err)
})
/**
* @description:
* @param {*} promise 当前promise实例
* @param {*} result then里面的执行的回调方法
* @param {*} resolve 成功的回调方法
* @param {*} reject 失败的回调方法
* @return {*}
*/
resolvePromise(promise, result, resolve, reject) {
// 防止返回的是promise实例自身
if(promise === result) reject(new TypeError('Chaining cycle detected for promise'))
// 返回的一个或者多个嵌套的promis对象
if(result && typeof result === 'object' || typeof result === 'function') {
let called
// try catch拦截报错 直接reject
try {
let then = result.then
// then是function说明返回的并非一层promise-----递归
if (typeof then === 'function') {
then.call(result, value => {
if (called) return
called = true
this.resolvePromise(promise, value, resolve, reject)
}, reason => {
if (called) return
called = true
reject(reason)
})
} else {
// 返回的就是简单的一层 可直接resolve
if (called) return
called = true
resolve(result)
}
} catch (error) {
if (called) return
called = true
reject(error)
}
} else {
// 类似直接return 一个字符串
resolve(result)
}
}
https://juejin.cn/post/6844903607968481287?searchId=20240113134833FBA77B9AE67E86A7C58B#heading-7
https://zhuanlan.zhihu.com/p/431677536
https://blog.csdn.net/urnotwang/article/details/131526496?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0-131526496-blog-120013821.235^v40^pc_relevant_anti_vip&spm=1001.2101.3001.4242.1&utm_relevant_index=1
https://juejin.cn/post/7102708871763853348#heading-5
手写js
vue-router原理
设计模式
观察者模式-发布订阅模式:
观察者模式:一个对象和其它依赖它的对象,当对象发生改变时,会通知依赖它的对象进行变更,触发更新. 观察者模式有两个对象,一个目标对象(依赖源)一个observe对象 目标对象拥有添加、删除、和通知一系列oberve的方法
观察者模式的缺点是 状态变更后执行统一更新方法 没细化
发布订阅模式:比观察者模式多了个事件通道(中介),订阅者和发布者通过事件通道相串联,订阅者可以通过事件通道(调用事件通道的订阅方法)订阅的任务类型,发布事件的对象(发布者)会通过发布对应类型事件(调用事件通道的发布事件方法)的方式通知订阅了该类型的订阅者
两者区别:
观察者模式与发布订阅模式都是定义了一个一对多的依赖关系,当有关状态发生变更时则执行相应的更新。
不同的是,在观察者模式中依赖于 Subject 对象的一系列 Observer 对象在被通知之后只能执行同一个特定的更新方法,而在发布订阅模式中则可以基于不同的主题去执行不同的自定义事件。相对而言,发布订阅模式比观察者模式要更加灵活多变。
juejin.cn/post/705544… juejin.cn/post/684490… juejin.cn/post/714832…
工厂模式:
juejin.cn/post/684490… juejin.cn/post/684490… //工厂方法模式
把相同的属性和方法放在一个函数里面,创建实例时候不需要关心逻辑处理过程,只需要调用方法传递参数生成实例。不需要写重复代码(创建和使用分离,降低耦合度)(根据传入的参数 执行不同的逻辑,或生成不同的实例)
工厂方法模式--实际就是把实际创建对象的工作推迟到子类中,在工厂函数里只做实例化操作(工厂方法我们只把它看作是一个实例化对象的工厂,它只做实例化对象这一件事情!)
类别 | 说明 |
---|---|
简单工厂 | 小作坊,适用于少量对象的创建,集中式管理,使用简单、扩展不便 |
工厂方法 | 正规小工厂,每种产品一个独立工厂,偏平化扩展 |
简单工厂 | 集团化大厂,产品种类、层级众多,需要多层级的工厂来管理,代码也稍复杂 |
单例模式
juejin.cn/post/684490… 特点:一个类只有一个实例,全局可访问,延迟执行(只在需要的时候执行)
vue双向数据绑定
for foreach map 区别
for可以用continue跳过当前循环中的一个迭代,用break直接跳过后面所有循环 但是可以继续执行函数后面语句(如果函数里有剩余语句的话) forEach 用continue会报错。但是可以使用return来跳出当前的循环,foreach可以改变原数组,for可以使用break来跳出整个循环,forEach正常情况无法跳出整个循环。 如果非要跳出forEach中的循环,可以抛出一个异常来处理(throw new error()方式),map不改变原数组,会映射一个新的数组
break是结束循环 但是会执行函数后面的人语句 continue是结束此次循环 继续执行下次循环 return是直接跳出函数 (
//使用return跳出当前循环
var arr = [1, 2, 3];
arr.forEach(function(item) {
if (item === 3) {
return;
}
console.log(item);
});
//对每一项进行操作,没有返回值,改变原属组
let arr = [1,2,3,4,5]
arr.forEach(function(item,index,arr){
arr[index] = item*2
})
console.log(arr) // [2,4,6,8,10]
for in 性能较差 因为会遍历除自身属性外的还有原型上的属性 耗时较长 遍历生成key 也就是键名 且不能保证遍历的顺序(无法保证属性的遍历顺序,可能会导致属性的无序输出)
for of 遍历可迭代对象(包括数组,字符串,set,map,等)不能遍历对象 生成的是value 有序遍历
for循环性能较高 while性能也较高
vue的diff算法
diff算法是用来比较虚拟dom的,作用是通过对比新的vnode和旧的vnode对比,只对变化了的dom进行操作,不更新整个视图。
echarts
虚拟列表
vue nextTick原理
cloud.tencent.com/developer/a…
稍微总结一下:就是$nextTick
将回调函数放到微任务或者宏任务当中以延迟它地执行顺序;(总结的也比较懒👶)
重要的是理解源码中它的三个参数的意思:
- callback:我们要执行的操作,可以放在这个函数当中,我们没执行一次
$nextTick
就会把回调函数放到一个异步队列当中; - pending:标识,用以判断在某个事件循环中是否为第一次加入,第一次加入的时候才触发异步执行的队列挂载
- timerFunc:用来触发执行回调函数,也就是
Promise.then
或MutationObserver
或setImmediate
或setTimeout
的过程
重要的三个过程:首先会将nextTick的回调函数放到callback异步队列里(是个数组),会进行一个去重(pending)判断,在一个事件循环里初次加入的才能挂载到异步队列,然后通过降级处理,把callback放到Promise.then
、MutationObserver
和setImmediate
,上述三个都不支持最后使用setTimeout;降级处理的目的都是将flushCallbacks
函数放入微任务或者宏任务,等待下一次事件循环时来执行,当事件循环到微任务或者宏任务的时候,遍历依次执行callback里的回调