面试题答案
一键面试函数构造函数与普通函数声明/表达式的选择及原因
- 普通函数声明/表达式优先:
- 原因:普通函数声明和表达式在解析代码时就被创建,具有更好的性能。它们在作用域链创建时就被定义,后续调用时直接从作用域中获取。而函数构造函数(如
new Function('param1', 'param2', 'return param1 + param2')
)是在运行时创建的,每次执行到该构造函数时都要创建一个新的函数对象,这会带来额外的性能开销。例如:
多次调用// 普通函数声明 function add1(a, b) { return a + b; } // 普通函数表达式 const add2 = function (a, b) { return a + b; }; // 函数构造函数 const add3 = new Function('a', 'b','return a + b');
add1
和add2
比调用add3
性能更好,因为add3
每次调用都要重新创建函数对象。 - 原因:普通函数声明和表达式在解析代码时就被创建,具有更好的性能。它们在作用域链创建时就被定义,后续调用时直接从作用域中获取。而函数构造函数(如
提升函数性能的具体措施
- 减少函数内部的全局变量访问:
- 说明:访问全局变量比访问局部变量慢,因为作用域链查找全局变量需要遍历更长的链。例如:
let globalVar = 10; function accessGlobal() { return globalVar; } function accessLocal() { let localVar = 10; return localVar; }
accessLocal
函数性能更好,因为它访问的是局部变量。可以将需要的全局变量缓存为局部变量来提升性能,如:let globalVar = 10; function accessGlobalOptimized() { let localVar = globalVar; return localVar; }
- 函数防抖和节流:
- 防抖(Debounce):在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。适用于搜索框输入等场景,避免频繁触发函数。例如,在搜索框输入时,频繁请求后端接口会造成性能问题,使用防抖可以在用户停止输入一段时间后再请求。实现如下:
function debounce(func, delay) { let timer; return function () { const context = this; const args = arguments; clearTimeout(timer); timer = setTimeout(() => { func.apply(context, args); }, delay); }; }
- 节流(Throttle):规定一个单位时间,在这个单位时间内,只能触发一次函数。如滚动事件,频繁触发滚动回调函数会影响性能,使用节流可以在一定时间间隔内只执行一次。实现如下:
function throttle(func, delay) { let lastTime = 0; return function () { const context = this; const args = arguments; const now = new Date().getTime(); if (now - lastTime >= delay) { func.apply(context, args); lastTime = now; } }; }