代码之家  ›  专栏  ›  技术社区  ›  Cristian Sanchez

为什么eval不能访问with语句下的作用域变量?

  •  7
  • Cristian Sanchez  · 技术社区  · 14 年前

    不能使用访问作用域变量吗 eval with

    例如:

    (function (obj) { 
       with (obj) {
          console.log(a); // prints out obj.a
          eval("console.log(a)"); // ReferenceError: a is not defined
       }
    })({ a: "hello" })
    

    编辑

    如果有人想知道我想想出什么样的可憎的东西,那就需要“邪恶”和 评估 --我想看看是否可以在另一个上下文中执行函数(用作回调),而不是在其中定义函数。不,我 可能 (咳嗽)不会在任何地方用这个。。比什么都好奇。

    (function (context,fn) { 
        with (context) 
           eval("("+fn+")()"); 
    })({ a: "hello there" }, function () { console.log(a); })
    
    4 回复  |  直到 14 年前
        1
  •  6
  •   Christian C. Salvadó    14 年前

    eval FunctionExpression

    当直接呼叫 评估

    (function (arg) {
      return eval('arg');
    })('foo');
    // should return 'foo', throws a ReferenceError from the WebKit console
    

    还有词汇环境:

    (function () {
      eval('var localVar = "test"');
    })();
    
    typeof localVar; // should be 'undefined', returns 'string' on the Console
    

    在上述函数中 localVar 应该在调用者的词汇环境中声明,而不是在全局上下文中声明。

    为了 FunctionDeclaration

    function test1(arg) {
      return eval('arg');
    }
    test1('foo'); // properly returns 'foo' on the WebKit console
    

    以及

    function test2() {
      eval('var localVarTest = "test"');
    }
    test2();
    typeof localVarTest; // correctly returns 'undefined'
    

    我已经能够在运行Windows Vista SP2的以下浏览器上重现此问题:

    • Chrome 6.0.472.25开发
    • WebKit夜间构建r64893
        2
  •  1
  •   David Titarenco    14 年前
    (function (obj) {
       with (obj) {
          alert(a); // prints out obj.a
          eval("alert(a)"); // ReferenceError: a is not defined
       }
    })({ a: "hello from a with eval" })
    
    function testfunc(a) { eval("alert(a)"); } testfunc("hello from a testfunc eval");
    
    (function (a) { eval("alert(a)"); })("hello from a function constructor eval")
    

    一切正常: http://polyfx.com/jstest.html

        3
  •  0
  •   Eric    14 年前

    Eval总是在全局范围内运行,不是吗?

        4
  •  0
  •   kennebec    14 年前

    抛开eval和with不谈,新的bowser包括ecma5 Function.prototype.bind方法来调用某个选定对象范围内的函数。

    对于较旧的浏览器,您可以伪造它-

    Function.prototype.bind= Function.prototype.bind || function bind(scope){
        var method= this;
        return function(){
            method.apply(scope, arguments);
        }
    }