You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript循环内函数声明性能对比:箭头函数vs外部函数

高频调用函数的实现疑问解答

问题背景

我有一个activeElemFromPoint函数,会在鼠标移动时被频繁调用,现有三种实现方案,同时有两个技术疑问:

  1. 是否必须使用方案3(循环外部定义函数)?
  2. 函数hasEvtNoAttr的两种声明方式3.1和3.2是否等价?

三种实现方案

方案1:箭头函数实现

/** @param { {clientX:number, clientY:number} } evt */
export function activeElemFromPoint(evt) {
    return document
        .elementsFromPoint(evt.clientX, evt.clientY)
        .find(el => !el.hasAttribute('data-evt-no'));
}

方案2:循环内定义普通函数实现

/** @param { {clientX:number, clientY:number} } evt */
export function activeElemFromPoint(evt) {
    return document
        .elementsFromPoint(evt.clientX, evt.clientY)
        .find(function (el) { return !el.hasAttribute('data-evt-no'); });
}

方案3:循环外部定义函数实现

/** @param { {clientX:number, clientY:number} } evt */
export function activeElemFromPoint(evt) {
    return document
        .elementsFromPoint(evt.clientX, evt.clientY)
        .find(hasEvtNoAttr);
}

// 3.1
/** @param {Element} el */
const hasEvtNoAttr = (el) => !el.hasAttribute('data-evt-no');

// 3.2
function hasEvtNoAttr(el) { return !el.hasAttribute('data-evt-no'); }

已知方案1每次调用时都会创建新的函数。


问题解答

1. 是否必须使用方案3?

不是必须的,但方案3在高频调用场景下有性能优势:

  • 方案1和2每次调用activeElemFromPoint时,都会在find方法内部创建新的函数实例。现代JS引擎对这类小函数的创建和回收有不错的优化,普通场景下几乎感知不到差异,但鼠标移动这类每秒可能触发数十到上百次调用的场景中,累计的内存分配和垃圾回收压力会被放大。
  • 方案3把判断函数提取到外部,每次find都复用同一个函数实例,能减少不必要的内存开销,性能敏感场景更推荐使用。
  • 如果项目对性能要求没那么极端,方案1/2的写法更简洁直观,可读性更高,完全可以正常使用。

2. hasEvtNoAttr的两种声明方式是否等价?

在当前业务场景下功能完全等价,但两者在JS语言特性上存在细微差异:

  • 变量提升:3.2的function声明会被变量提升,在代码中声明位置之前就能调用;而3.1的const箭头函数不会提升,必须在声明之后才能使用。
  • this绑定:箭头函数没有自身的this,会继承外层作用域的this;普通函数的this由调用方式决定。但在这个场景里,find方法仅传递遍历到的元素作为参数,不会用到this,所以不影响功能。
  • 可修改性:3.1用const声明,无法被重新赋值;3.2的function声明本质是给变量赋值,在非块级作用域中可以被重新覆盖。

内容的提问来源于stack exchange,提问作者user1167761

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 13:20:29