webpack压缩后使用eval执行动态数学公式报错问题咨询
问题根因
- webpack打包默认开启严格模式,严格模式下
eval内部的var声明仅在eval自身的执行上下文内有效,不会提升到外层函数作用域,所以你在eval里声明的A、B等变量,外层代码无法访问。 - webpack压缩混淆时会把模块内导入的局部变量名(比如你引入的
angle/intersect等工具函数)替换为短字符名,但eval里的公式字符串是静态内容,不会跟着同步替换,导致执行时找不到对应函数。
最优解决方案
不要直接使用eval,改为通过new Function构造动态计算函数,显式传入所有公式依赖的上下文,完全避开压缩和作用域问题,实现代码如下:
import {intersect, distance, angle, dist} from './utils' // 配置公式用到的所有工具函数映射,键名必须和公式内写的函数名完全一致 const formulaMethods = { intersect, distance, angle, dist } function analysis() { const data = require('./config/analyses.json') const instance = { available_analyses: function() { return Object.keys(data); }, run_analysis: function(name, points) { const analysis = data[name] const equations = analysis['equations'] const results = [] // 拼接执行上下文的键和值 const execKeys = [...Object.keys(formulaMethods), ...Object.keys(points)] const execValues = [...Object.values(formulaMethods), ...Object.values(points)] for (const equation of equations) { const formula = equation.formula // 构造动态计算函数,参数名和公式内的变量/函数名完全匹配 const calcFn = new Function(...execKeys, `return ${formula}`) results.push({ name: formula, value: calcFn(...execValues) }) } return results; } } return instance; }
该方案的优势:
- 不受webpack压缩混淆、严格模式的影响
- 不会污染全局作用域
- 执行上下文可控,安全性比直接
eval更高
备选兼容方案(不推荐)
如果一定要沿用eval的写法,可以把所有依赖的函数和变量挂载到全局对象上,示例:
// 初始化时把工具函数挂载到全局window import {intersect, distance, angle, dist} from './utils' window.intersect = intersect window.distance = distance window.angle = angle window.dist = dist // run_analysis内生成点变量时也挂载到全局 for (const [key, value] of Object.entries(points)) { eval(`window.${key} = [${value}];`); }
该方案的缺陷是会污染全局变量,可能和页面其他脚本产生命名冲突。
内容的提问来源于stack exchange,提问作者jtomasrl
相关产品推荐
相关产品推荐

