JavaScript核心
闭包和作用域
实现一个防抖或节流函数
延迟执行,频繁触发,只有最后一次生效
场景:等待用户操作完成后执行1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29fucntion debounceFn(fn, delay) {
let timer = null;
return function(...args) {
timer && clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this,args);
}, delay)
}
}
节流: 控制执行频率,固定时间段触发
场景:滚动、拖拽、窗口调整
定时器版本
function throttleFn(fn, delay) {
let timer = null;
return function(...args) {
if (!timer) {
timer = setTimeout(() => {
fn.apply(this,args);
//执行完毕以后清空定时器
timer = null
}, delay)
}
}
}
时间戳版本闭包在模块化中应用
- 立即执行函数 + 闭包
- ES Modules export / import
原生模块作用域
模块化本质:通过作用域隔离和依赖管理,实现代码高内聚低耦合
如何避免闭包引起的内存泄漏
及时解除引用:手动将变量设为null
不要引用多余的变量
注意dom元素的引用,可以只引用dom的某个属性,而非整个dom对象
合理使用模块化和类: 通过类的生命周期管理闭包,在不需要时主动清理
避免在循环中创建闭包:把函数作为入参浏览器的垃圾回收机制
被闭包引用的变量无法被垃圾回收机制识别为不再使用找出不再被程序引用的对象,释放他们所占用的内存
如何找出:
判断标准:类的生命周期
原型和继承
- 实现一个继承方案并比较各种继承方式的优缺点
- 原型链继承
- 构造函数继承
- 组合继承
- 原型式继承
1
2
3
4
5function createObject(proto) {
function F() {}
F.prototype = proto;
return new F();
} - ES6 Class 继承
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16Class Parent {
constructor(name) {
this.name = name;
}
sayName() {
}
}
Class Child extends Parent {
constructor (name, age) {
super(name);
this.age = age;
}
}
- new操作符的内部实现原理
- 创建了一个空对象
- 将新对象的原型指向构造函数的prototype
obj.proto = constructor.portotype - 绑定this并执行构造函数
- 返回执行结果,如果执行结果不是对象或者null 返回新创建的对象
1
- Class与原型继承的区别
异步编程
Promise实现原理以及手写Promise
async/await 底层实现原理
基于Generator函数和Promise实现的
async 函数 相当于自动执行的generator函数,无需手动调用next()
await 会暂停函数执行,等待右侧表达式的Promise完成状态变更如何处理多个并行异步请求的错误
Promise.all(promises)
Promise.allSettled(promises)