我正在尝试在特定上下文中执行eval。我发现答案here很有用。但是,我在Chrome版本53.0.2785.143 m中收到以下行为。没试过其他浏览器。我正在使用的代码如下:
function evalInContext(js, context) {
return function() { return eval(js); }.call(context);
}
console.log(evalInContext('x==3', { x : 3})) // Throws
console.log(evalInContext('this.x==3', { x : 3})) // OK
但是我期望第一次打电话给evalInContext
不要扔。有什么想法可能会发生这种情况吗?
答案 0 :(得分:6)
虽然我推荐@trincot提供的答案,特别是伟大的链接。我在这里发布我遇到的问题的解决方案
function evalInContext(scr, context)
{
// execute script in private context
return (new Function( "with(this) { return " + scr + "}")).call(context);
}
with(this)
表达式允许context
对象的成员变量出现在表达式scr
的执行范围内。
将this answer归功于类似的问题
答案 1 :(得分:3)
这是另一种方法(用ES6编写):
lst <- strsplit(df[,1], ", ")
do.call(rbind, lapply(lst, `length<-`, max(lengths(lst))))
# [,1] [,2]
#a "John" "3 years"
#b "Mokobe" "11 years"
#c "Ivan" NA
为乔纳斯·威尔姆斯提供答案。
这是我的解释,因为我最初并不了解它是如何工作的:
(new Function(...Object.keys(context), codeYouWantToExecute))(...Object.values(context));
与创建函数并将其分配给let example = new Function('a', 'b', 'return a+ b')
相同:
example
之后,您可以像这样调用function(a,b) {
return a + b
}
:example
返回8。
但是,假设您不想将example(2,6)
创建的函数分配给变量,而是想立即调用它。
然后您可以执行以下操作:
new Function
本文顶部的代码段实质上是在做同样的事情。它使用散布运算符来传递new Function('a', 'b', 'return a+ b')(2,6)
对象的键,如下所示:
context
。然后,它将调用新创建的函数,并使用传播运算符传递与每个键对应的值。
最后,这是编译到ES5的答案:
new Function(key1, key2, key3... lastkey, codeYouWantToExecute)
答案 2 :(得分:2)
解析变量x
的方式与上下文无关。它由范围规则解决:任何闭包是否定义了该变量?如果没有,请查看全局对象。在任何时候都不会通过查看上下文来解析变量。
您可以查看this article。
行为并非特定于eval
,与其他功能相同:
"use strict";
var obj = { x : 3};
var y = 4;
function test() {
console.log(this.x); // 3
console.log(typeof x); // undefined
}
test.call(obj);
function test2() {
console.log(this.y); // 4
console.log(typeof y); // number
}
test2.call(window);
&#13;
答案 3 :(得分:0)
这将在给定的上下文中计算表达式,而无需在vars前面加上“ this”。
有警告,但工作正常。
还可以在表达式中合并自定义函数。
只需调用一个“求值”函数,传入您的表达式,上下文和一个可选函数即可。
上下文必须是平面结构(无嵌套元素),并且函数必须在字符串表达式内称为“ fn”。在这种情况下,答案打印11:
var expression = "fn((a+b)*c,2)";
var context = { a: 1, b: 2, c: 3 };
var func = function(x,y){return x+y;};
function evaluate(ex, ctx, fn) {
return eval("var "+JSON.stringify(ctx).replace(/["{}]/gi, "").replace(/:/gi, "=")+", fn="+fn.toString()+";"+ex);
}
var answer = evaluate(expression, context, func);
console.log(answer);
答案 4 :(得分:0)
无法发表评论,所以我发帖,Joe 的回答很棒,但如果字符串包含多个语句(如 x++; y++; x+y;
),则永远不会执行 y++
部分,因为它在第一个语句处返回。
通过此修改,所有语句都将被执行,最后一条语句将作为返回值。
<块引用>function evalInScopeAndContext(scr, scopeAndContext)
{
// execute script in private context
return (new Function( "with(this) { return eval('" + scr + "'); }")).call(scopeAndContext);
}
我还更改了参数名称,因为该参数既用作作用域又用作上下文,它们是不同的东西。
警告 1:
使用此函数时,this.x
将等于 x
且无法更改,因为范围的 this
属性(如果存在)将被遮蔽。
如果你执行 evalInScopeAndContext('this', {a:1, b:2, this:3})
答案将是 {a:1, b:2, this:3}
而不是 3
。
要访问属性 this
,您必须改为编写 this.this
,我认为它无法修复。
警告 2:
外部作用域(从这个函数的调用者到 window
)可以被访问和修改,除非被作用域对象遮蔽。
因此,如果您计划执行诸如 location = 'house';
之类的操作,但忘记在作用域对象中插入 location
键,您将执行 window.location = 'house'
并可能造成损坏。
相反,this.location = 'house';
始终是安全的,因为 this
始终存在并且只会将 location
键添加到提供的范围对象中,因此您可能希望始终使用 this.
作为前缀