hiu*_*kim 21 javascript scope eval
有什么办法可以在特定范围内执行eval()(但不是全局)?
例如,以下代码不起作用(在第二个语句中未定义)因为它们位于不同的范围内:
eval(var a = 1);
eval(alert(a));
Run Code Online (Sandbox Code Playgroud)
如果可能的话,我想动态创建一个范围.例如(语法肯定是错误的,但只是为了说明这个想法)
var scope1;
var scope2;
with scope1{
eval(var a = 1); eval(alert(a)); // this will alert 1
}
with scope2{
eval(var a = 1); eval(a++); eval(alert(a)); // this will alert 2
}
with scope1{
eval(a += 2); eval(alert(a)); // this will alert 3 because a is already defined in scope1
}
Run Code Online (Sandbox Code Playgroud)
有关如何实现这样的事情的任何想法?谢谢!
chi*_*ens 19
这对我来说效果最好:
const scopedEval = (scope, script) => Function(`"use strict"; ${script}`).bind(scope)();
Run Code Online (Sandbox Code Playgroud)
用法:
scopedEval({a:1,b:2},"return this.a+this.b")
Run Code Online (Sandbox Code Playgroud)
Jos*_*eph 17
你可以使用"use strict"来包含eval本身内的eval代码.
其次,
eval严格模式代码不会将新变量引入周围范围.在普通代码中,eval("var x;")将变量x引入周围函数或全局范围.这意味着,通常,在包含对eval每个不引用参数或本地变量的名称的调用的函数中,必须在运行时将其映射到特定的定义(因为这eval可能引入了一个隐藏外部变量的新变量).在严格模式下,eval仅为要计算的代码创建变量,因此eval不会影响名称是指外部变量还是某个局部变量
var x = 17; //a local variable
var evalX = eval("'use strict'; var x = 42; x"); //eval an x internally
assert(x === 17); //x is still 17 here
assert(evalX === 42); //evalX takes 42 from eval'ed x
Run Code Online (Sandbox Code Playgroud)
如果使用"use strict"声明函数,则其中的所有内容都将以严格模式执行.以下内容与上述相同:
function foo(){
"use strict";
var x = 17;
var evalX = eval("var x = 42; x");
assert(x === 17);
assert(evalX === 42);
}
Run Code Online (Sandbox Code Playgroud)
在作用域中创建要作为局部变量存在的变量.然后,从该函数返回一个本地定义的函数,该函数具有单个参数并对其进行调用eval.该实例eval将使用其包含函数的范围,该函数嵌套在顶级函数的范围内.顶级函数的每次调用都会创建一个带有eval函数新实例的新范围.为了保持动态,您甚至可以eval在顶级函数中使用调用来声明该范围的本地变量.
示例代码:
function makeEvalContext (declarations)
{
eval(declarations);
return function (str) { eval(str); }
}
eval1 = makeEvalContext ("var x;");
eval2 = makeEvalContext ("var x;");
eval1("x = 'first context';");
eval2("x = 'second context';");
eval1("window.alert(x);");
eval2("window.alert(x);");
Run Code Online (Sandbox Code Playgroud)
https://jsfiddle.net/zgs73ret/
简单如馅饼。
// Courtesy of Hypersoft-Systems: U.-S.-A.
function scopeEval(scope, script) {
return Function('"use strict";return (' + script + ')').bind(scope)();
}
scopeEval(document, 'alert(this)');Run Code Online (Sandbox Code Playgroud)
这里的方法是允许上下文对象参数化表达式的计算。
首先使用Function() 构造函数创建一个函数,该构造函数接受上下文的每个键以及要计算的表达式;主体返回计算后的表达式。然后使用上下文的所有值和要计算的表达式调用该函数。
function scopedEval(context, expr) {
const evaluator = Function.apply(null, [...Object.keys(context), 'expr', "return eval('expr = undefined;' + expr)"]);
return evaluator.apply(null, [...Object.values(context), expr]);
}
// Usage
const context = {a: 1, b: 2, c: {d: 3}};
scopedEval(context, "a+b+c.d"); // 6
Run Code Online (Sandbox Code Playgroud)
通过使用Function.prototype.apply ,不需要事先知道参数的数量和名称。因为参数的作用域是函数,所以evaluator它们可以从表达式直接访问(而不是 require this.a)。