MST

星途 面试题库

面试题:JavaScript基于类对象和闭包模块的并发性能调优及内存管理

在大型JavaScript项目中,基于类对象和闭包模块实现的并发操作面临性能瓶颈和内存泄漏风险。请详细阐述你会从哪些方面进行性能调优,比如优化异步任务调度算法、合理使用缓存等;以及如何进行有效的内存管理,避免闭包引起的内存泄漏,需要结合具体的优化策略和代码示例说明。
29.6万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

性能调优

  1. 优化异步任务调度算法
    • 策略:使用async/await结合Promise.allSettledPromise.race来更好地控制并发任务。Promise.allSettled可以等待所有任务完成(无论成功或失败),而Promise.race可以在第一个任务完成时就返回结果。这样可以避免不必要的等待,提高执行效率。
    • 代码示例
// 使用Promise.allSettled
async function asyncTasks() {
    const task1 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('Task 1 completed');
        }, 1000);
    });
    const task2 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('Task 2 completed');
        }, 1500);
    });
    const results = await Promise.allSettled([task1, task2]);
    results.forEach((result, index) => {
        if (result.status === 'fulfilled') {
            console.log(`Task ${index + 1} succeeded:`, result.value);
        } else {
            console.log(`Task ${index + 1} failed:`, result.reason);
        }
    });
}
asyncTasks();
// 使用Promise.race
async function asyncTasksRace() {
    const task1 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('Task 1 completed');
        }, 1000);
    });
    const task2 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('Task 2 completed');
        }, 1500);
    });
    const firstResult = await Promise.race([task1, task2]);
    console.log('First completed task:', firstResult);
}
asyncTasksRace();
  1. 合理使用缓存
    • 策略:利用WeakMap或普通对象作为缓存。对于频繁调用且结果不经常变化的函数,可以缓存其返回值。对于类对象的方法调用结果缓存,可以在类实例中维护一个缓存对象。对于闭包模块,可以在闭包内部维护一个缓存变量。
    • 代码示例
// 使用普通对象缓存函数结果
const cache = {};
function expensiveCalculation(a, b) {
    const key = `${a}-${b}`;
    if (cache[key]) {
        return cache[key];
    }
    const result = a + b;
    cache[key] = result;
    return result;
}
// 使用WeakMap缓存类对象方法结果
const instanceCache = new WeakMap();
class MyClass {
    expensiveMethod() {
        if (!instanceCache.has(this)) {
            const result = /* 复杂计算 */ 42;
            instanceCache.set(this, result);
        }
        return instanceCache.get(this);
    }
}

内存管理

  1. 避免闭包引起的内存泄漏
    • 策略:确保在闭包不再需要时,切断对外部变量的引用。如果在类的方法中使用闭包,要注意在适当的时候(如类实例销毁时),清除闭包内部对类实例的引用。
    • 代码示例
class LeakyClass {
    constructor() {
        this.data = 'Some large data';
    }
    // 可能导致内存泄漏的闭包
    createLeakyClosure() {
        return () => {
            return this.data;
        };
    }
}
class FixedClass {
    constructor() {
        this.data = 'Some large data';
    }
    createSafeClosure() {
        const self = this;
        return () => {
            const temp = self.data;
            // 清除引用
            self = null;
            return temp;
        };
    }
}
  1. 及时释放资源
    • 策略:对于使用setTimeoutsetInterval等创建的定时器,在不需要时要及时清除。对于事件监听器,在不再需要监听时要移除。
    • 代码示例
// 清除定时器
let timer;
function startTimer() {
    timer = setTimeout(() => {
        console.log('Timer executed');
    }, 1000);
}
function stopTimer() {
    clearTimeout(timer);
}
// 移除事件监听器
const button = document.getElementById('myButton');
function handleClick() {
    console.log('Button clicked');
}
button.addEventListener('click', handleClick);
// 移除事件监听器
button.removeEventListener('click', handleClick);