JavaScript传递eval变量

9
我有一个eval函数,需要从PHP执行JavaScript。但我需要传递元素,这样我就可以在用户点击的链接上放置鼠标提示。
var globalEval = function globalEval(src, element) {
        if (window.execScript) {
            window.execScript(src);
            return;
        }
        var fn = function(element) {
            window.eval.call(window,src);
        };
        fn(element);
    };

我使用以下方法传递$(this)元素:

globalEval(js_code, $(this));
// js_code is = alert(element);

我遇到了一个未定义的元素错误,这个元素在globalEval();中被定义了,我该怎么解决?

如果我正确地假设src始终是一个字符串,那么如果您执行window.eval.call(window,'(function (element) {'+src+'})')(element);会发生什么? - Paul S.
@PaulS。好的,我会尝试并回复。 - Basit
3个回答

12

这是一个作用域问题,因为全局的 eval 没有在与变量 element 相同的作用域中调用代码。如果您必须使用 eval,即使 eval 是有害的,您也必须以一种让您能够在所需环境中调用代码的方式来使用它。其中一种方法是将其包装为匿名函数,并提供所选环境变量的参数。

例如:

window.eval.call(window,'(function (element) {'+src+'})')(element);

这意味着src字符串被解析但没有被eval调用,因为它返回一个匿名函数。然后您调用它并传递数据,例如在此情况下是element

使用var element = document.body, src = 'console.log(element.tagName)';进行测试,你将看到它记录"BODY"。请注意,如果您想以这种方式设置全局变量(或函数),它们必须明确声明为全局变量(window.foobar = ...),否则它们将在匿名函数完成后被垃圾回收。


1
为什么不直接使用本地的 eval(src),它会捕获 element - Esailija
@Esailija 因为我喜欢把事情搞得过于复杂。不,我的答案中的方式意味着你通过传递变量来指定环境并保护你当前的环境(因为函数是ByVal,诸如element = otherElm这样的更改不会影响你调用它的位置),而本地的eval(src)将使用当前环境。它还提供了其他关于调用它的选项(例如var-ing它/使用.call)。我并不是说eval永远是“安全”的,但至少这种方式意味着你可以在你想要的环境中调用它(假设src是有效的JavaScript)。 - Paul S.
@PaulS。非常感谢。现在这个可以正常工作:)。顺便问一下,window.execScript('(function (element) {'+src+'})')(element); 这个也能用吗? - Basit
2
你应该使用函数构造器:它可以更好地报告(语法)错误。 - geocar
@geocar +1 因为我同意,但这并不涉及到 eval,这也不是 OP 的问题。 - Paul S.
显示剩余5条评论

7

如果你只是想在评估一些代码时让this被设置,那么可以尝试以下方法:

// Code you want to evaluate
var code = 'return this.whatever'

// What you want "this" bound to:
var that = { whatever: 69 }

// Now do this:
var result = new Function(code).call(that)

使用 Function 构造函数可以达到预期效果;使用全局 eval 会带来许多不必要的负担,其中有些可能会让你感到意外。如果不需要使用它则最好避免。
如果你真的想将其命名为 `element`,那么 Function 构造函数 也可以做到:
code = 'alert(element)'
var use_element = 69
result = new Function("element", code).call(this, use_element)

我喜欢你的建议。只是想知道它是否支持旧版浏览器以及任何来自PHP的JavaScript动态代码是否能够正常执行而没有错误? - Basit
@Basit - 请参考http://aptana.com/reference/api/Function.html了解浏览器兼容性。PHP与此无关,您可以简单地执行以下操作:`result = new Function("element", <?= json_encode($code) ?>).call(this, use_element)`。 - geocar

0
如果回调函数在同一个DOM中,则在eval之前将全局变量设置为repo,以保留该变量。然后在要调用的函数中使用全局变量。
var response_repo;
function someFunc($callback){
 ....
 success: function(result) {
            response_repo = result;
            eval($callback+'();');
        },
 ....
 }


 callBackFunc(){
  $data=response_repo;
 }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接