为什么Javascript没有';不让函数从自身内部重新定义自身?

为什么Javascript没有';不让函数从自身内部重新定义自身?,javascript,scope,definition,redefinition,Javascript,Scope,Definition,Redefinition,以代码为例: 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 = functi

以代码为例:

    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. 

基本上,我已经尝试了所有可能的方法,但似乎都没有成功。有人能解释一下原因吗?

您正在成功地重新定义函数,只是调用它的表达式已经抓住了旧的函数引用:调用表达式中发生的第一件事是对定义要调用的函数的东西进行求值,请参阅规范的:

11.2.3函数调用

生产CallExpression:MemberExpression参数的计算方法如下:

  • 设ref为计算MemberExpression的结果
  • 设func为GetValue(ref)
  • 让argList作为计算参数的结果,生成参数值的内部列表(见11.2.4)
  • 如果类型(func)不是对象,则引发TypeError异常
  • 如果IsCallable(func)为false,则引发TypeError异常
  • 如果类型(ref)为参考,则
    a)如果IsPropertyReference(ref)为真,则
    一,。将此值设为GetBase(ref)。
    b)否则,ref的基础是环境记录
    一,。让thisValue成为调用GetBase(ref)的隐式thisValue具体方法的结果
  • 否则,类型(ref)不是引用。
    a)让该值未定义
  • 返回对func调用[[Call]]内部方法的结果,提供thisValue作为this值,提供list argList作为参数值
  • 步骤1和2发生在重新定义函数之前

    当然,解决办法是按照您期望的顺序(|)进行:



    旁注:在Chrome(V8)中工作很有趣(它在IE6版本的JScript中也可以工作;但是,JScript有很多问题)。它不应该工作,在Firefox(SpiderMonkey)、Opera(Carakan)或IE9(Chakra)中也不应该工作。

    JavaScript对运算符参数的求值顺序有严格的从左到右规则。我猜这包括函数调用操作符,这意味着第一个
    a
    是在表达式之前计算的。

    只是出于好奇,你为什么要这么做?第一个对我来说确实很有用(Chrome 18)在Chrome和IE中工作得很好……作为一个一般提示:在浏览器的JS控制台中尝试一下。如果你这么做了,你会很快发现JS函数可以做你想做的事情;你只要按正确的顺序做就行了。首先评估var r=a(2),然后评估
    a('2*2='+r)
    有趣的是,它在Chrome中工作。它不应该(见我的答案),在Firefox或Opera中也不应该。
    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);