Confusion about different [[Scope]] between Function Declaration and Function Expression

Kang-Hao (Kenny) Lu kennyluck at csail.mit.edu
Tue Dec 11 23:03:51 PST 2012


(Resending on behalf of 张立理 <otakustay at live.com> because his mail
didn't go through.)

According to [section 13 Function
Definition](http://ecma-international.org/ecma-262/5.1/#sec-13) of
ECMAScript-262 5.1, the **Function Declaration** production and the
**Function Expression** production are nearly the same, except when they
are in the process of [Create Function
Objects](http://ecma-international.org/ecma-262/5.1/#sec-13.2), in which
case they pass different **Scope** argument: Function Declaration passes
the **VariableEnvironment** while Function Expression passes the
**LexicalEnvironment**. This confuses me a little.


Suppose we have this code:


    function test() {
        var x = 1;
        var o = { x: 2 };
        with (o) {
            eval('function foo() { console.log(x); }');
            eval('var bar = function() { console.log(x); }');
        }
        foo();
        bar();
    }
    test();


If I understand correctly, here are 2 facts:


- outside `with` statement, the **VariableEnvironment** and
**LexicalEnvironment** refer to the same object, here we name it `outerEnv`.
- inside `with` statement, we have a new **LexicalEnvironment** (object
environment), the **VariableEnvironment** stays the same, here we name
the new **LexicalEnvironment** `innerEnv`.


The problem lies in the 2 direct `eval` calls. Without the **strict**
flag, the `eval` function shares the same **LexicalEnvironment** and
**VariableEnvironment** as its calling context. When the `eval` is
invoked in a `with` statement, **VariableEnvironment** and
**LexicalEnvironment** are different, so we expect `foo` and `bar`
outputs different numbesr: `foo` should output `1` and `bar` should
output `2`.


The fact is, the edge version of Chrome, Firefox and IE7-10, all output
`2` and `2`.


Why is ECMAScript-262 5.1 documenting a behavior that's different from
nearly all modern browsers? Should these browsers consider their
implementations buggy, or should our standard change a little? Anyway, I
could not image a situation when **Function Declaration** and **Function
Expression** should use different objects as their `[[Scope]]` internal
property, why not use **LexicalEnvironment** of its calling context as
all browsers do?


The `catch` statement has the same problem:


    function test() {
        var x = 1;
        try {
            throw 2;
        }
        catch (x) {
            eval('function foo() { console.log(x); }');
            eval('var bar = function() { console.log(x); }');
        }
        foo();
        bar();
    }
    test();


Thanks.



Gray Zhang
-------------
电子邮件:otakustay at live.com
微博:@otakustay
博客:http://otakustay.com


More information about the es-discuss mailing list