面试题答案
一键面试内存优化避免内存泄漏
- 合理使用闭包:闭包容易导致内存泄漏,确保在闭包内对外部变量的引用在不需要时能够被正确释放。例如:
function outerFunction() {
let largeObject = { /* 一个很大的对象 */ };
return function innerFunction() {
// 使用 largeObject
console.log(largeObject.someProperty);
// 当 innerFunction 不再需要使用 largeObject 时,将其设为 null
largeObject = null;
};
}
- 事件绑定与解绑:如果在对象上绑定了事件监听器,在对象销毁时要确保解绑这些监听器。
class MyClass {
constructor() {
document.addEventListener('click', this.handleClick.bind(this));
}
handleClick() {
console.log('Clicked');
}
destroy() {
document.removeEventListener('click', this.handleClick.bind(this));
}
}
- 对象属性清理:当对象不再使用时,清理对象上不必要的属性引用,防止这些属性占用内存。
function createObject() {
let obj = {
largeData: [/* 大量数据 */],
otherProperty: 'Some value'
};
// 使用完 obj 后,如果 largeData 不再需要
obj.largeData = null;
return obj;
}
代码解耦提高可扩展性与维护性
- 单一职责原则:每个类或函数只负责一项明确的功能。
class DataFetcher {
fetchData() {
// 逻辑:从服务器获取数据
return Promise.resolve({ data: 'fetched data' });
}
}
class DataProcessor {
processData(data) {
// 逻辑:处理获取到的数据
return data.data.toUpperCase();
}
}
- 依赖注入:通过构造函数或函数参数传递依赖,而不是在类内部创建依赖。
class DataPresenter {
constructor(dataFetcher, dataProcessor) {
this.dataFetcher = dataFetcher;
this.dataProcessor = dataProcessor;
}
async presentData() {
let data = await this.dataFetcher.fetchData();
let processedData = this.dataProcessor.processData(data);
console.log(processedData);
}
}
// 使用
let fetcher = new DataFetcher();
let processor = new DataProcessor();
let presenter = new DataPresenter(fetcher, processor);
presenter.presentData();
- 模块化:将相关功能封装成模块,通过
export
和import
来管理依赖。
// dataFetcher.js
export class DataFetcher {
fetchData() {
return Promise.resolve({ data: 'fetched data' });
}
}
// dataProcessor.js
export class DataProcessor {
processData(data) {
return data.data.toUpperCase();
}
}
// main.js
import { DataFetcher } from './dataFetcher.js';
import { DataProcessor } from './dataProcessor.js';
class DataPresenter {
constructor(dataFetcher, dataProcessor) {
this.dataFetcher = dataFetcher;
this.dataProcessor = dataProcessor;
}
async presentData() {
let data = await this.dataFetcher.fetchData();
let processedData = this.dataProcessor.processData(data);
console.log(processedData);
}
}
let fetcher = new DataFetcher();
let processor = new DataProcessor();
let presenter = new DataPresenter(fetcher, processor);
presenter.presentData();
代码架构示例
结合上述原则,构建一个简单的 JavaScript 子类系统示例:
// 基类
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a sound`);
}
}
// 子类
class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
speak() {
console.log(`${this.name} (${this.breed}) barks`);
}
// 采用单一职责原则,将获取叫声的逻辑分离
getBarkSound() {
return 'Woof';
}
}
// 模块:声音处理器
class SoundProcessor {
constructor() {
this.sounds = [];
}
addSound(sound) {
this.sounds.push(sound);
}
playSounds() {
this.sounds.forEach(sound => console.log(sound));
}
}
// 主程序
let dog = new Dog('Buddy', 'Golden Retriever');
let soundProcessor = new SoundProcessor();
// 依赖注入
soundProcessor.addSound(dog.getBarkSound());
soundProcessor.playSounds();
在此示例中,通过单一职责原则将获取叫声逻辑分离,通过依赖注入将 SoundProcessor
与 Dog
解耦,提高了可扩展性与维护性。同时在内存管理方面,确保对象属性在不再需要时可以自然释放内存,避免内存泄漏。