React Native v0.70.6中eval行为与Node/浏览器不一致问题咨询
我在React Native v0.70.6版本的应用中尝试动态解析代码,示例代码如下:
var myVar = 3; console.log('myVar', myVar); eval('myVar = 8'); console.log('myVar', myVar);
执行后结果不符合预期,两次输出均为myVar 3;但在Node CLI或浏览器控制台中执行相同代码,能得到正确结果:先输出myVar 3,再输出myVar 8。此前该功能正常,但我在更新日志中未找到相关变更记录,请问React Native中的eval实现是否有改动?
问题原因
React Native v0.70+默认启用的Hermes引擎对eval的处理逻辑发生了变化。为了性能优化,Hermes会将所有eval调用按间接eval处理,无论你写的是直接调用形式。间接eval的执行上下文是全局作用域,而非当前的词法作用域,因此无法修改当前作用域下的var变量。
而Node和浏览器环境中的直接eval是在当前作用域内执行,所以能正常修改外部变量。
解决方案
将变量挂载到全局作用域
把需要修改的变量放到全局对象上,让eval能在全局作用域访问并修改它:global.myVar = 3; console.log('myVar', global.myVar); eval('myVar = 8'); console.log('myVar', global.myVar);执行后会得到预期的
myVar 3和myVar 8输出。使用
Function替代eval
通过Function构造函数动态执行代码,利用全局作用域传递变量:global.myVar = 3; console.log('myVar', global.myVar); new Function('myVar = 8')(); console.log('myVar', global.myVar);禁用Hermes引擎(不推荐)
如果必须保留原有的eval行为,可以在项目配置中禁用Hermes,切换回JSC引擎。但这会丢失Hermes带来的启动速度、内存占用等性能优化,仅作为临时应急方案。
补充说明
官方更新日志中没有单独提及这个eval行为变更,因为这是Hermes引擎性能优化过程中附带的逻辑调整。Hermes对词法作用域的处理更严格,目的是降低动态代码执行带来的性能损耗,同时提升代码运行的可预测性。
内容的提问来源于stack exchange,提问作者c4k

