在特定上下文中调用 eval()

IT技术 javascript
2021-02-14 08:40:21

我有以下javaScript“类”:

A = (function() {
   a = function() { eval(...) };
   A.prototype.b = function(arg1, arg2) { /* do something... */};
})();

现在让我们假设在 eval() 中我传递的字符串包含使用一些参数调用 b 的表达式:

 b("foo", "bar")

但是后来我得到了 b 未定义的错误。所以我的问题是:如何在 A 类的上下文中调用 eval?

6个回答

实际上,您可以通过函数进行抽象完成此操作:

var context = { a: 1, b: 2, c: 3 };

function example() {
    console.log(this);
}

function evalInContext() {
    console.log(this);        //# .logs `{ a: 1, b: 2, c: 3 }`
    eval("example()");        //# .logs `{ a: 1, b: 2, c: 3 }` inside example()
}

evalInContext.call(context);

因此,您可以使用call所需的函数contexteval在该函数内运行。

奇怪的是,这似乎在本地对我有用,但在Plunkr不起作用!?

对于简洁(并且可以说是多汁的;)版本,您可以逐字复制到您的代码中,请使用:

function evalInContext(js, context) {
    //# Return the results of the in-line anonymous function we .call with the passed context
    return function() { return eval(js); }.call(context);
}

编辑不要混淆this和“范围”

//# Throws an error as `this` is missing
console.log(evalInContext('x==3', { x : 3}))

//# Works as `this` is prefixed
console.log(evalInContext('this.x==3', { x : 3})) 

虽然可以这样做

function evalInScope(js, contextAsScope) {
    //# Return the results of the in-line anonymous function we .call with the passed context
    return function() { with(this) { return eval(js); }; }.call(contextAsScope);
}

为了缩小差距,这不是 OP 提出的问题,它使用的是with正如 MDN 所说

不推荐使用 with 语句,因为它可能是混淆错误和兼容性问题的根源。有关详细信息,请参阅下面“描述”部分中的“歧义反义词”段落。

但它确实有效,而且还不算太“坏”(不管这意味着什么),只要人们意识到这种调用可能引起的奇怪之处。

@estevalInScope("window", { window: 1 })返回1evalInContext需要使用this.window(例如evalInContext("this.window", { window: 1 }))返回1
2021-04-17 08:40:21
您尝试过哪个浏览器(版本)?它不工作,按规范(和所有现代浏览器),你得到undefined(或马虎模式函数的全局窗口对象)this的valueexample
2021-04-25 08:40:21
您应该真正更新您的答案以反映您在评论中提供的正确示例。
2021-05-01 08:40:21
我遇到了与此类似的问题,发现上述方法不起作用。我在这里发布了一个可能的解决方案:stackoverflow.com/a/40109254/1972493
2021-05-09 08:40:21
@Campbeln 解释了一切。谢谢!
2021-05-10 08:40:21

如何在给定的上下文中调用 eval?3个字。使用闭包。

var result = function(str){
  return eval(str);
}.call(context,somestring);

砰。

“somestring”是您希望使用 eval 命令运行的代码。参见developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
2021-04-26 08:40:21
如何在上下文中禁用对全局变量的访问?像“窗口”“文档”
2021-04-26 08:40:21
多么优雅的解决方案
2021-04-27 08:40:21
请注意,somestring 中的表达式必须使用“this”访问上下文属性,例如 this.property。否则你得到一个没有定义的属性ReferenceError。var context = {'live-usa': 'no', 'alcohol': 'never', 'height': '65', 'weight': '140' }; var 表达式 = "this.height == '' || this.weight == ''"; var 结果 = function(str){ return eval(str); }.call(上下文,表达式);// 在这种情况下返回 false。
2021-05-03 08:40:21
somestring这里的目的是什么?
2021-05-05 08:40:21

编辑

即使 eval.call 和 eval.apply 不强制正确传递上下文,您也可以使用闭包来强制 eval 在@Campbeln 和@user3751385 的答案中提到的所需上下文中执行

我的原答案

这不可能。eval 仅在本地上下文(直接使用)或全局上下文(即使您使用 eval.call)中调用。

例如, a = {}; eval.call(a, "console.log(this);"); //prints out window, not a

有关更多信息,请在此处查看这篇很棒的文章

不,不,...这可以很容易地完成,如我在下面的回复中所述。
2021-04-15 08:40:21
嗯……这不完全正确。您可以eval使用特定上下文执行,其中this===theContext您传入({ neek: true }例如)。诀窍是您必须使用.call另一个函数,然后调用eval,您不能.call eval像示例中那样直接完成此操作。在下面查看我的答案,了解如何完成此操作。
2021-05-01 08:40:21

绝对不是正确的答案,请不要使用with语句,除非您知道自己在做什么,但出于好奇,您可以这样做

例子

    var a = {b: "foo"};
    with(a) {
        // prints "foo"
        console.log(eval("b"));  
        
        // however, "this.b" prints undefined
        console.log(eval("this.b"));
    
        // because "this" is still the window for eval
        // console.log(eval("this")); // prints window

// if you want to fix, you need to wrap with a function, as the main answer pointed out
        (function(){
	         console.log(eval("this.b")); // prints foo
        }).call(a);     
    }
    
    // so if you want to support both    
    with (a) {
    	(function (){
        console.log("--fix--");
      	console.log(eval("b")); // foo
        console.log(eval("this.b")); // foo
      }).call(a);
    }

with是在函数内创建块作用域的失败尝试,这是ES6 的let设计目的。(但不完全是,打开并阅读资源链接)

这也是唯一允许您在不需要this.
2021-04-28 08:40:21
我认为这个答案绝对没问题。with 语句是这个问题的完美解决方案。只有当您在任何地方或在大范围内使用“with”时,歧义才会成为问题。:)
2021-05-03 08:40:21

这是一篇讨论eval()在不同上下文中运行的文章

http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context

通常你用eval.call()来做eval.apply()

以下是有关eval()及其用例的信息:

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/eval

@Rocket:我认为您对 jsFiddle 的看法是正确的。由于他们正在使用框架获得一个新窗口,因此他们只是将您的代码包装在<script>包含在该框架内容中的 a 中。,是的,它似乎thisArgeval.call()应该是封闭环境的全局对象。
2021-04-18 08:40:21
@Rocket:不确定这是否是浏览器环境,但可能是一个安全的赌注。顺便说一句,您的 jsFiddle 不起作用,因为您没有传递window对象。
2021-04-25 08:40:21
停止阅读“eval 很方便”的第一篇文章,第二篇没有提到 eval 的任何用例,而是在常见的新手错误是使用 eval 的情况下如何替换 eval 的使用。
2021-05-04 08:40:21
eval.call给了我一个错误:EvalError: The "this" object passed to eval must be the global object from which eval originated
2021-05-05 08:40:21
@Rocket:是的,这很少见,当然在浏览器环境中。在 NodeJS 之类的东西中,它的module系统通过将文件中的代码连接成一个开始和结束字符串,然后对其进行评估来工作。jsFiddle 可能是另一个例子,但我假设。是的,我假设new Function使用eval,或者至少与 eval 共享引擎盖下的代码。虽然有区别。
2021-05-13 08:40:21