其他
垃圾回收机制
只有函数内的变量才能被回收,也就是局部变量的生命周期结束;
两种回收机制
- 标记清除:变量进入环境时标记“进入”,变量离开环境时,标记“离开”;
- 引用计数:当变量 A(引用类型)赋值给了变量 B,则 A 引用次数 +1;当 B 不再指向A时,A 引用次数 -1;
js
// 标记清除
function test(){
const a = 10 ; // 被标记,进入环境
}
test(); // 执行完毕 之后 a 又被标离开环境,被回收
// 引用计数 (很少使用了)
function test() {
var a = {}; // a指向对象的引用次数为1
var b = a; // a指向对象的引用次数加1,为2
var c = a; // a指向对象的引用次数再加1,为3
var b = {}; // a指向对象的引用次数减1,为2
}
内存泄漏
循环引用、闭包、DOM 泄露、定时器泄漏
js
// 意外的全局变量:在函数中没有声明就赋值的变量,或者通了 this 声明,但最后挂到 window 上了
// 闭包,维持函数内部局部变量,使其无法释放
function bindEvent() {
const obj = document.createElement('XXX');
const unused = function () {
console.log(obj, '闭包内引用obj obj不会被释放');
};
obj = null; // 解决方法
}
// 定时器泄漏
const someResource = getData();
const t = setInterval(function() {
const node = document.getElementById('Node');
if (node) {
node.innerHTML = JSON.stringify(someResource)); // 处理 node 和 someResource
}
}, 1000);
clearInterval(t); // 如果不关计时器,node 对象和回调函数都不会被回收
// 对 DOM 元素的监听,当不监听的时候,取消事件监听
// 对 DOM 元素的引用,不需要时取消应用
设计模式
1️⃣ 工厂模式
js
function createPerson(name, age, job) {
const obj = new Object();
obj.name = name;
obj.age = age;
obj.job = job;
obj.sayName = function () { console.log(this.name); };
return obj;
}
const person1 = createPerson("Nicholas", 29, "Software Engineer");
const person2 = createPerson("Greg", 27, "Doctor");
这种工厂模式虽然可以解决创建多个类似对象的问题,但没有解决对象标识问题(即新创建的对象是什么类型)
2️⃣ 构造函数模式
js
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function () { console.log(this.name); };
}
const person1 = new Person("Nicholas", 29, "Software Engineer");
const person2 = new Person("Greg", 27, "Doctor");
person1.sayName(); // Nicholas
person2.sayName(); // Greg
Person 构造函数内部代码和 createPerson 工厂函数基本一致,只是有以下区别:
- 没有显式地创建对象
- 属性和方法直接复制给了 this
- 没有 return
构造函数的问题在于其定义的方法会在每个实例上都创建一遍,造成资源浪费
3️⃣ 原型模式
js
function Person() { };
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function () { console.log(this.name); };
const person1 = new Person();
person1.sayName(); // "Nicholas"
const person2 = new Person();
person2.sayName(); // "Nicholas"
console.log(person1.sayName == person2.sayName); // true