今日复习计划:内存泄漏
一. 前端知识
1. 内存泄漏
1.1 闭包变量泄漏
function fn() {
let test = "test";
return () => {
console.log("hhhhh");
};
}
let fn1 = fn();
fn1();
上诉代码不会造成内存泄漏,因为fn内的变量test并没有被引用
function fn() {
let test = "test";
return () => {
console.log(test);
};
}
let fn1 = fn();
fn1();
上诉代码中,test变量被引用,所以test不会被回收,造成内存泄漏。那如何正确使用呢?如下:
function fn() {
let test = "test";
return () => {
console.log(test);
};
}
let fn1 = fn();
fn1();
fn1 = null
1.2 隐式全局变量
不使用声明符进行变量声明,变量会变成全局变量,对于全局变量的回收特别困难,会造成内存泄漏。
function fn() {
test = "111";
console.log(test);
}
fn();
解决方案:正确使用变量声明或者使用严格模式。如果非要使用全局变量,应当正确关闭引用。
let global = {a:1}
xxxx
global = null
1.3 游离DOM引用
<div id="root">
<ul id="ul">
<li></li>
<li></li>
<li id="li3"></li>
<li></li>
</ul>
</div>
<script>
let root = document.querySelector("#root");
let ul = document.querySelector("#ul");
let li3 = document.querySelector("#li3");
// 由于ul变量存在,整个ul及其子元素都不能GC
root.removeChild(ul)
// 虽置空了ul变量,但由于li3变量引用ul的子节点,所以ul元素依然不能被GC
ul = null
// 已无变量引用,此时可以GC
li3 = null
</script>
1.4 定时器
setTimout、setInterval、requestAnimationFrame如不使用对应API正确关闭,则会导致回调函数里变量以及回调函数里的依赖没有正确回收。
let test = "1";
setTimeout(() => {
let test2 = "2";
console.log(test, test2);
}, 1000);
上述代码中,变量test1、test2都不会被回收。使用clearTime、clearInterval、cancelAnimationFrame清除对应的定时器。
1.5 事件监听
function fn() {}
window.addEventListener("resize", fn);
window.removeEventListener("resize", fn);
1.6 引用型数据类型(map,object)
当使用 Map 或 Set 存储对象时,同 Object 一致都是强引用,如果不将其主动清除引用,其同样会造成内存不自动进行回收。
let obj = {name: 'cxm'}
obj = null // {name: 'cxm'} 被正常回收
Map、Set中的key如为引用型,因为是强引用,所以key值的引用型数据将永远不会被回收。应当使用weakMap、weakSet替代。
let key = { name: "map" };
let map = new Map();
map.set(key, "test");
map.clear(); // key对象不会被回收
let weakMap = new WeakMap();
weakMap.set(key, "test");
weakMap.clear(); // weakMap的引用为弱引用,故key对象会被正常回收
二. 算法
// Given an object, then convert it to a new object structure
// For example:
const entry = {
a: {
b: {
c: {
dd: 'abcdd',
},
},
d: {
xx: 'adxx',
},
e: 'ae',
},
};
// When we invoke the "convertObject" method and pass the parameter "entry" object: convertObject(entry)
// The result is:
// {
// 'a.b.c.dd': 'abcdd',
// 'a.d.xx': 'adxx',
// 'a.e': 'ae',
// };
// Please complete the convertObject method
function convertObject(o) {
let res = {}
for(let key in o){
let item = o[key]
console.log(Object.prototype.toString.call(item));
if(Object.prototype.toString.call(item) === '[object Object]'){
let tempObj = convertObject(item)
for(let sKey in tempObj){
let sTempObj = tempObj[sKey]
let connectKey = `${key}.${sKey}`
res[connectKey] = sTempObj
}
}else{
res[key] = item
}
}
return res
}
console.log( convertObject(entry));
三. 面经
1. 不可变量
2. Promise的原理
3. React18
4. Redux原理
5. webpack Tree-shaking实现
总结:
今天是被虐的一天,准备不足。被问了一些知识盲区,感觉这些年其实光顾着写业务,一些底层的知识面还是很匮乏。
四. 其他
He said, one day you’ll leave this world behind,
so live a life you will remenber