面试题答案
一键面试利用函数属性实现模块间通信方案
- 方案描述:在 JavaScript 中,函数是一等公民,可以拥有属性。我们可以利用这一点来实现模块间通信。例如,定义一个全局的事件中心函数
eventCenter
,给它添加on
和emit
属性。
const eventCenter = function() {};
eventCenter.on = function(eventName, callback) {
if (!this.events) {
this.events = {};
}
if (!this.events[eventName]) {
this.events[eventName] = [];
}
this.events[eventName].push(callback);
};
eventCenter.emit = function(eventName, ...args) {
if (this.events && this.events[eventName]) {
this.events[eventName].forEach(callback => callback(...args));
}
};
在各个模块中,可以通过 eventCenter.on
来监听事件,通过 eventCenter.emit
来触发事件,从而实现模块间通信。
2. 优势:
- 解耦性高:模块之间不需要直接引用,降低了模块之间的耦合度,使得各个模块可以独立开发、测试和维护。
- 灵活性强:可以在运行时动态地添加和移除事件监听器,适应不同的业务场景变化。
- 易于理解和实现:基于函数属性的方式相对简单直观,对于开发人员来说容易理解和上手。
3. 可能面临的挑战:
- 命名冲突:如果多个模块使用相同的事件名称,可能会导致意外的事件触发和监听,需要良好的命名规范来避免。
- 内存管理:如果事件监听器没有及时移除,可能会导致内存泄漏,特别是在单页应用中,页面组件销毁时需要注意清理相关的事件监听器。
- 调试困难:由于事件是异步触发的,当出现问题时,调试起来可能相对困难,需要借助调试工具和良好的日志记录来定位问题。
利用函数属性实现性能监控方案
- 方案描述:可以给关键函数添加属性来记录函数的执行时间等性能信息。例如,定义一个装饰器函数
performanceMonitor
,它接收一个函数并返回一个新的函数,新函数会在执行前后记录时间,并将执行时间记录在原函数的executionTime
属性上。
function performanceMonitor(func) {
return function(...args) {
const start = Date.now();
const result = func.apply(this, args);
const end = Date.now();
func.executionTime = end - start;
return result;
};
}
// 使用示例
function heavyFunction() {
// 模拟一些复杂计算
for (let i = 0; i < 1000000; i++);
}
const monitoredFunction = performanceMonitor(heavyFunction);
monitoredFunction();
console.log(monitoredFunction.executionTime);
- 优势:
- 非侵入式:通过装饰器模式,在不修改原函数内部代码的情况下实现性能监控,对原有业务逻辑影响小。
- 针对性强:可以精确监控特定函数的性能,方便定位性能瓶颈。
- 数据收集方便:将性能数据直接记录在函数属性上,便于后续收集和分析。
- 可能面临的挑战:
- 影响性能:虽然记录执行时间本身开销较小,但如果监控的函数非常频繁调用,可能会对整体性能产生一定影响。
- 全面性问题:这种方式只能监控单个函数,对于涉及多个函数调用的复杂业务流程的性能监控,需要额外的处理来串联各个函数的性能数据。