6

コードを考えてみましょう:

    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. 

そして基本的に私はすべての可能な方法を試しましたが、どちらもその仕事をしていないようです。誰かが理由を説明できますか?

4

2 に答える 2

8

関数を正常再定義しています。それを呼び出す式がすでに古い関数参照を取得しているだけです。呼び出し式で最初に発生するのは、呼び出す関数を定義するものが評価されることです。のセクション11.2.3を参照してください。仕様:

11.2.3関数呼び出し

本番のCallExpression:MemberExpression引数は、次のように評価されます。

  1. MemberExpressionを評価した結果をrefとします
  2. funcをGetValue(ref)とします。
  3. argListを引数の評価の結果とし、引数値の内部リストを生成します(11.2.4を参照)
  4. Type(func)がObjectでない場合は、TypeError例外をスローします。
  5. IsCallable(func)がfalseの場合、TypeError例外をスローします。
  6. Type(ref)がReferenceの場合、
      a)IsPropertyReference(ref)がtrueの場合、
          i。thisValueをGetBaseref)とします。
      b)それ以外の場合、refのベースは環境レコード
          iです。thisValueを、 GetBase ( ref )のImplicitThisValue具象メソッドを呼び出した結果とします。
  7. それ以外の場合、Type(ref)は参照ではありません。
    a)thisValueを未定義にします。
  8. funcで[[Call]]内部メソッドを呼び出した結果を返し、thisValueをthis値として提供し、リストargListを引数値として提供します。

手順1と2は、関数が再定義される前に実行されます。

解決策はもちろん、期待した順序で物事を実現することです(実際の例|ソース):

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);

補足:最初の例がChrome(V8)で機能するのは興味深いことです(IE6バージョンのJScriptでも機能しますが、JScriptには多くの問題がありました)。これは動作しないはずであり、Firefox(SpiderMonkey)、Opera(Carakan)、またはIE9(Chakra)では動作しません。

于 2012-03-30T11:08:10.053 に答える
1

JavaScriptには、演算子引数の評価の順序について、厳密な左から右への規則があります。これには関数呼び出し演算子が含まれていると思います。つまり、最初の演算子aは式の前に評価されます。

于 2012-03-30T11:08:25.073 に答える