考虑代码:
window.a = function(x){
var r = x*2;
window.a =alert; // redefines itself after first call
return r;
};
a('2 * 2 = '+a(2)); // doesn't work. it should've alerted "2 * 2 = 4"
这也不起作用:
window.a = function(x){
alert(x);
window.a = function(x){ // redefines itself after first call
var r = x*2;
return r;
}
};
a('2 * 2 = '+a(2)); // doesn't work. it should've alerted "2 * 2 = 4"
这两者都没有:
window.a = function(x){ alert(x); window.c = window.a; window.a = window.b; window.b = window.c; };
window.b = function(x){ var r = x*2; window.c = window.b; window.b = window.a; window.a = window.c; return r; };
a('2 * 2 = '+a(2)); // doesn't work.
基本上我已经尝试了所有可能的方法,似乎都没有做到这一点。有人可以解释一下原因吗?
答案 0 :(得分:8)
您的是成功重新定义的功能,它只是表达调用它已经抓住了老函数的引用:这种情况发生在通话中表达的第一件事是,东西定义调用什么功能评估,请参阅规范的Section 11.2.3:
11.2.3函数调用
生产 CallExpression:MemberExpression Arguments 的计算方法如下:
- 让 ref 成为评估 MemberExpression 的结果。
- 让 func 为GetValue( ref )。
- 让 argList 成为评估 Arguments 的结果,生成一个参数值的内部列表(见11.2.4)。
- 如果Type( func )不是Object,则抛出TypeError异常。
- 如果IsCallable( func )为false,则抛出TypeError异常。
- 如果Type( ref )是Reference,那么
a)如果IsPropertyReference( ref )为真,那么
我。让 thisValue 为GetBase( ref )。
b)否则, ref 的基础是环境记录
我。让 thisValue 成为调用GetBase的ImplicitThisValue具体方法的结果( ref )。- 否则,Type( ref )不是Reference。
a)让 thisValue 未定义。- 返回调用的结果[[调用]]上的 FUNC 内部的方法,提供的 thisValue 作为该值,并提供所述列表 ARGLIST 作为参数值。
醇>
步骤1和2发生在重新定义函数之前。
解决方案当然是按照您期望的顺序(live example | source)来实现:
window.a = function(x){
var r = x*2;
window.a =alert; // redefines itself after first call
return r;
};
var val = a(2);
a('2 * 2 = '+ val);
旁注:有趣的是your first example在Chrome(V8)中有效(它也适用于IE6的JScript版本;但是,JScript有很多的问题)。它应该不起作用,并且不适用于Firefox(SpiderMonkey),Opera(Carakan)或IE9(Chakra)。
答案 1 :(得分:1)
JavaScript对运算符参数的评估顺序有严格的从左到右的规则。我猜这包括函数调用操作符,这意味着在表达式之前评估第一个a
。