面试题答案
一键面试可能出现的内存问题场景
- 循环引用:当两个对象通过原型链相互引用时,会导致垃圾回收机制无法回收它们所占用的内存。例如:
function A() {}
function B() {}
A.prototype.b = new B();
B.prototype.a = new A();
这里A
和B
的实例通过原型链相互引用,即使它们不再被外部引用,垃圾回收器也无法释放它们的内存。
2. 大量基于同一原型的对象:创建大量基于同一原型的对象时,如果原型上绑定了大量数据或方法,每个对象都会共享这些原型上的内容,随着对象数量的增加,内存占用会显著上升。例如:
function Person() {}
Person.prototype = {
name: '',
age: 0,
hobbies: ['reading', 'traveling'], // 大量数据
printInfo: function() {
console.log(`Name: ${this.name}, Age: ${this.age}`);
}
};
// 创建大量Person对象
for (let i = 0; i < 10000; i++) {
new Person();
}
内存优化方法
- 解决循环引用:在对象不再使用时,手动解除循环引用。例如:
function A() {}
function B() {}
A.prototype.b = new B();
B.prototype.a = new A();
// 解除循环引用
A.prototype.b = null;
B.prototype.a = null;
这样垃圾回收器就可以回收A
和B
实例所占用的内存。
2. 处理大量基于同一原型的对象:
- 拆分原型:将不常用的属性或方法从原型中分离出来,避免所有对象都共享这些内容。例如:
function Person() {}
Person.prototype = {
name: '',
age: 0,
printInfo: function() {
console.log(`Name: ${this.name}, Age: ${this.age}`);
}
};
// 不常用的hobbies属性单独处理
Person.prototype.getHobbies = function() {
return ['reading', 'traveling'];
};
- **使用WeakMap或WeakSet**:对于一些临时性的关联数据,可以使用`WeakMap`或`WeakSet`。它们不会阻止对象被垃圾回收,因为它们对对象的引用是弱引用。例如:
const weakMap = new WeakMap();
function Person() {}
const person = new Person();
weakMap.set(person, { extraData: 'Some data' });
// 当person不再被其他地方引用时,它和其关联的WeakMap数据都可被回收
person = null;