如何比对两个结构相似的JS文件的功能等价性
仅覆盖标识符重命名场景的JS代码等价判定方案
首先明确:通用场景下的JS功能等价判定是和停机问题等价的不可判定问题,不存在能覆盖所有边界情况的通用解法,但你提到的仅需要识别基础标识符重命名的轻量需求,有非常多现成的成熟方案,完全不需要从零手写AST解析、遍历逻辑。
你的核心思路是完全正确的:只要把两份代码中所有用户自定义标识符,按照固定、可预测的规则(比如按作用域内首次出现的顺序,统一重命名为v1/v2/v3这类序列名)做归一化处理,之后直接比对归一化后的代码字符串或者AST结构哈希,就能精准识别出仅变量/常量/函数名不同的等价代码。
现成可直接复用的方案
- 基于Terser的确定性重命名能力实现
Terser是目前最常用的JS压缩工具,本身支持高度自定义的压缩规则。你只需要关闭所有会改动代码结构的优化项(包括常量折叠、死代码删除、语句合并、函数内联、表达式简化等),仅保留标识符重命名能力,同时配置重命名的命名序列为固定从v1开始递增的规则即可。
对你给出的两段示例代码,经过相同配置的Terser处理后,都会输出完全一致的结果:
之后直接做字符串相等比对,就能判定二者功能等价。const v1=1;console.log(v1) - 基于现有代码相似度检测工具的精准模式
主流的JS代码相似度、抄袭检测工具本身就内置了标识符归一化逻辑,你只需要把检测阈值拉到最高,关闭跨结构匹配、语法容错类的规则,工具会自动忽略标识符命名的差异,直接比对AST结构、字面量值、调用关系,零额外开发就能适配你的需求。 - 基于Babel生态的现成归一化预设
Babel生态已经有成熟的AST归一化插件,只需要把待检测的代码传入,配置仅做标识符重命名归一化,就能直接输出标准化后的代码,不需要自己写AST遍历、作用域处理的逻辑。
注意:使用以上所有方案时,必须保证两份代码的处理配置完全一致,且全程关闭会修改代码执行逻辑、语法结构的优化规则,避免出现误判。只要配置正确,这类方案对基础标识符重命名场景的识别准确率可以达到100%,足够覆盖绝大多数日常使用场景。
内容的提问来源于stack exchange,提问作者zanerock
相关产品推荐
相关产品推荐

