关于函数定义和函数表达式的[[Scope]]问题

根据[ECMA标准第13节](http://ecma-international.org/ecma-262/5.1/#sec-13), 创建**函数定义**和**函数表达式**的过程几乎一样,唯一的区别是调用[创建函数对象](http://ecma-international.org/ecma-262/5.1/#sec-13.2)这一过程时会传递不同的**Scope**参数,**函数定义**用的是**VariableEnvironment**,**函数表达式**用的是**LexicalEnvironment**。不过现实好像有点不一样。 来看下面的代码:     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(); 我没理解错的话,这段代码:
- 在`with`语句外面,**VariableEnvironment**和**LexicalEnvironment**指向的是同一个对象,我这里叫它`outerEnv`。- 在`with`语句里面,会有一个新的**LexicalEnvironment**产生(是个object environment),而**VariableEnvironment**保持不变,这个新的**LexicalEnvironment**就叫它`innerEnv`。
关键的问题是,当2个`eval`调用时,这个显然是直接调用,并且不是严格模式。这种情况下,`eval`会共享外层环境的**LexicalEnvironment**和**VariableEnvironment**,因此它的代码中,**LexicalEnvironment**和**VariableEnvironment**是不同的对象,即**LexicalEnvironment**为`innerEnv`,**VariableEnvironment**是`outerEnv`。
然后在`eval`中,分别创建了一个**函数定义`foo`**和一个**函数表达式`bar`**,那么它们的`[[Scope]]`应该不一样,其中`foo`的是`outerEnv`,而`bar`的是`innerEnv`。
因此当这2个函数被执行时,`foo`应该输出`1`,`bar`输出`2`。不过事实是,Chrome、Firefox的最新版本,IE7-10,统一都是输出`2`和`2`。
同样的问题也出在`catch`语句中:     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();
现在的问题是,为什么ECMA要定义出一个和几乎所有浏览器(Opera和Safari等我没测,感觉八九不离十)都不同的行为。这种算是标准有问题,还是所有浏览器都应该修复呢?
其实我觉得,正常来说,**函数定义**也应该用**LexicalEnvironment**就合理了,而且**函数定义**通常是在进入函数时就被创建的,此时**LexicalEnvironment**和**VariableEnvironment**肯定是相同的,仅有`eval`配合`with`或`catch`才会出现这种情况。
Gray Zhang-------------------------------------------otakustay@live.comhttp://www.otakustay.com 		 	   		  

Received on Wednesday, 12 December 2012 07:46:03 UTC