eval 的使用
需求
假如有个对象是 { a : { b : 1 }, c: true }
,希望输入字符串 {{a.b}}
得到结果 1
;输入 c
得到结果 true
。
试了 stackoverflow 的写法,代码如下:
function evalInScopeOld(js, contextAsScope) {
// Return the results of the in-line anonymous function.
// call with the passed context
return function() {
with(this) {
return eval(js);
};
}.call(contextAsScope);
}
弹出报错Uncaught SyntaxError: Strict mode code may not include a with statement
。代码出现 with 就无法执行。
于是参考 vue 的 _render 的写法,代码如下
function evalInScope(js, contextAsScope) {
let fn = new Function(`with(this){return eval("${js}");}`);
return fn.call(contextAsScope);
}
可以正常运行。
原因分析如下:
MDN网站的描述:
由 Function 构造器创建的函数不会创建当前环境的闭包,它们总是被创建于全局环境,因此在运行时它们只能访问全局变量和自己的局部变量,不能访问它们被 Function 构造器创建时所在的作用域的变量
js运行的三个阶段:
简单语法分析阶段:这个阶段还没分析new Function里面的语法,所以fn里面的with不会报错;而fn1里面的with报语法错误
预编译阶段
解释执行阶段:new Function的执行发生在解释执行阶段,已经不在简单语法分析阶段
参考链接
[^1] Uncaught SyntaxError: Strict mode code may not include a with statement
[^2] vue的_render函数的with语句为什么不报错 - 简书 (jianshu.com)
最后更新于