0

So of the two ways of dynamic code evaluation (Function constructor vs eval()), the former one do not create closure but the later one does? Why is a closure not formed while using Function constructors to evaluate some code? Is this behavior mandated by the ECMA specification?

Geek
  • 26,489
  • 43
  • 149
  • 227

2 Answers2

3

Is this behavior mandated by the ECMA specification?

It is. Section 15.3.2.1 describes the algorithm that is executed when new Function is evaluated. Note the last step:

11. Return a new Function object created as specified in 13.2 passing P as the FormalParameterList and body as the FunctionBody. Pass in the Global Environment as the Scope parameter and strict as the Strict flag.

The scope in which the function will be run is the global scope, not the current scope where the call is made, hence it cannot form a closure.

On the other hand, code executed through eval is run the current scope (§10.4.2):

b. Set the LexicalEnvironment to the same value as the LexicalEnvironment of the calling execution context.
c. Set the VariableEnvironment to the same value as the VariableEnvironment of the calling execution context.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • But why is it designed this way? What would be the side effect if function objects were created with the local scope? – Geek Aug 03 '13 at 13:59
  • If you want them in the local scope, why not write them as literals? – Paul S. Aug 03 '13 at 14:00
  • @PaulS. the function body and the parameters may come from outside. So may not be possible to write as a literal. – Geek Aug 03 '13 at 14:02
  • @Geek: I cannot answer you that. Probably only someone who worked on the specification can. – Felix Kling Aug 03 '13 at 14:07
  • @FelixKling I understand. My question was is this mandated by the specification and the answer is *yes*. You also quoted the source. So I am accepting your answer. – Geek Aug 03 '13 at 14:10
  • @Geek: It's safer for example. If you need to eval code, then you can choose not to let if affect your local scope by using the `Function` constructor instead of `eval`. See the discussions on where, when and how [not] to to use eval. – Bergi Aug 03 '13 at 14:45
  • @Bergi probably you wanted to put a link in your comment. – Geek Aug 03 '13 at 14:50
  • @Geek: Nah, I wanted you to do a web search :-) The [top SO questions](http://stackoverflow.com/search?q=%5bjavascript%5d%20use%20eval) would be http://stackoverflow.com/q/543533, http://stackoverflow.com/q/197769 and http://stackoverflow.com/q/86513 – Bergi Aug 03 '13 at 14:59
2

Here is a way to see closures being effected by Function and eval.

var z = 0;
(function () {                                 // Local    | Global
    var x = 0, y = 0;                          // x  y  z  | x      y      z
    console.log(x, y, z);                      // 0  0  0  |
    console.log(window.x, window.y, window.z); //          | undef  undef  0
    new Function('var x = 1; y = 1; z = 1')(); // Function set 1
    console.log(x, y, z);                      // 0  0  1  |
    console.log(window.x, window.y, window.z); //          | undef  1      1
    eval('var x = 2; y = 2; z = 2');           // Eval set 2
    console.log(x, y, z);                      // 2  2  2  |
    console.log(window.x, window.y, window.z); //          | undef  1      2
}());

You can see that eval is working in the current scope whereas Function is invoked as a function in the global scope.

But really, please try to avoid using either.

Paul S.
  • 64,864
  • 9
  • 122
  • 138
  • Dynamic evaluation is very useful and can be used to gain significant performance boosts. Using `Function` doesn't cause your code to be dynamically scoped either like `with` and `eval` do,. – Esailija Aug 03 '13 at 14:53