6

Does javascript allow aliasing eval? The first part of the following code behaves unexpectedly (displays 1, 1), but the second part does not (displays 1, 2). A reference to the ECMA script or mozilla docs will be helpful, I couldn't find one.

<html>
<script type="application/javascript;version=1.8">
    (function(){
        eval('var testVar=1');
        alert(testVar);
        var eval2=eval;
        eval2('var testVar=2');
        alert(testVar);
    })();

    (function(){
        eval('var testVar=1');
        alert(testVar);
        eval('var testVar=2');
        alert(testVar);
    })();
</script>
</html>
4

2 回答 2

7

You can't "alias" eval and expect it to behave the same. Simple as that. Why? eval isn't a function.

What is happening is that when you call eval2, you are setting the variable "cache" to work with the global variables. Therefore, by setting a variable inside of it, you are setting a global variable. However, upon exiting, the variable "cache" returns back to the function scoped one. That's why the second alert shows 1 - the global variable is being shadowed by the function level one.

This is noted in Annex E (page 239) of ECMAScript (emphasis mine)

10.4.2: In Edition 5, indirect calls to the eval function use the global environment as both the variable environment and lexical environment for the eval code. In Edition 3, the variable and lexical environments of the caller of an indirect eval was used as the environments for the eval code.

The full definition on "Entering Eval Code" is defined in §10.5.2 (page 58) (emphasis mine)

  1. If there is no calling context or if the eval code is not being evaluated by a direct call (15.1.2.1.1) to the eval function then,
    • Initialise the execution context as if it was a global execution context using the eval code as C as described in 10.4.1.1.
  2. Else,
    • Set the ThisBinding to the same value as the ThisBinding of the calling execution context.
    • Set the LexicalEnvironment to the same value as the LexicalEnvironment of the calling execution context.
    • Set the VariableEnvironment to the same value as the VariableEnvironment of the calling execution context.
  3. If the eval code is strict code, then
    • Let strictVarEnv be the result of calling NewDeclarativeEnvironment passing the LexicalEnvironment as the argument.
    • Set the LexicalEnvironment to strictVarEnv.
    • Set the VariableEnvironment to strictVarEnv.
  4. Perform Declaration Binding Instantiation as described in 10.5 using the eval code.
于 2013-07-21T09:21:13.247 回答
2

在您使用的第一种情况下eval,它使用执行它的函数范围。当您分配evaleval2然后执行相同的语句时,它似乎使用的是window上下文(全局范围)而不是函数上下文。这就是为什么您在第一种情况下看到相同的值 1,因为testVar函数内部是 1,外部window.testVar是 2。您可以通过执行以下代码片段来证明这一点

<script>
(function(){
        eval('var testVar=1');
        alert(window.testVar);
        var eval2=eval;

        eval2('var testVar=2');
        alert(window.testVar);
    })();

    (function(){
        eval('var testVar=1');
        alert(testVar);
        eval('var testVar=2');
        alert(testVar);
    })();
</script>

实际上,根据Mozilla Developer Network,您不能为 eval 取别名。

于 2013-07-21T09:28:04.300 回答