ES3和ES5中函数调用(function call) 的浏览器实现差异.

来源:互联网 发布:网络电话机终端 编辑:程序博客网 时间:2024/04/30 17:56

1.var obj = {};
2.obj.foo( obj.foo = function(){ console.log("new func"); } );
3.obj.foo();//new func

有些浏览器执行到第二行处报错,有些继续执行打印出"new func"
执行到第二行时,
一种是先解析出obj.foo 对象,然后解析参数,再执行函数调用,显然,解析obj.foo时,foo不存在。
一种是先解析参数,然后解析obj.foo,最后执行函数调用。

ES 5中函数调用的顺序
1. Let ref be the result of evaluating MemberExpression.
 2. Let func be GetValue(ref).
 3. Let argList be the result of evaluating Arguments, producing an internal list of argument values
 4. If Type(func) is not Object, throw a TypeError exception.
 5. If IsCallable(func) is false, throw a TypeError exception.
 6. (snip)

So, func indicates shoud be Undefined and it should throw TypeError by step4.
因此报错


下面的例子按ES 5

1.varo = {
2.    test: function() {alert('origin')}
3.};
4.o.test(o.test =function(){ alert('changed'); });//origin
5.o.test();//changed

  


但是.Chrome17-, IE8- 第四行会打印changed .  而 Firefox0.8+,Safai3+, Opera9.2+,IE9+ 则第四行都打印origin.  

 

出现这个问题的根源,我们通过翻看 ES3和ES5,可以找到原因.  原来ES3和ES5,在此处是有冲突的. 道格拉斯认为ES3是不合理的. 所以更改了这里的逻辑.

ES3:

Function Calls
The production CallExpression : MemberExpression Arguments is evaluated as follows:
1. Evaluate MemberExpression.
2. Evaluate Arguments, producing an internal list of argument values (see 11.2.4).
3. Call GetValue(Result(1)).

 

ES5:

11.2.3 Function Calls
The production CallExpression : MemberExpression Arguments is evaluated as follows:

1. Let ref be the result of evaluating MemberExpression.
2. Let func be GetValue(ref).
3. Let argList be the result of evaluating Arguments, producing an internal list of argument values (see 11.2.4).

 

可见ES5 对MemberExpression 也就是这里的函数名部分的表达式所获取的引用,进行getValue运算是早于 对实参列表进行evalute的.

而ES3则恰恰相反.  

 参考

http://www.cnblogs.com/_franky/archive/2011/12/02/2271864.html
原创粉丝点击