クローズド

4635 ワード

もとの問題は次の通りです   
function func(n,o) {
    console.log(o)
    return {
        func:function(m){
            return func(m,n);
        }
    };
}

var a = func(0);a.func(1);a.func(2);
var b = func(0).func(1).func(2).func(3);
var c = func(0).func(1);c.func(2);  
  • のコードの中に三つのfunc関数が現れていますので、この三つのfun関数の関係は、どの関数がどの関数と同じなのかを最初に分かります.
  • function func(n,o) {
      console.log(o)
      return {
        func:function(m){
          //...
        }
      };
    }
      まず最初のfunc関数を見て、標準具名関数宣言に属しています.新たに作成された関数です.彼の戻り値はオブジェクトの字面量表現で、新しいobjectに属しています.
      この新しいオブジェクトの内部には、funcともいう属性が含まれています.上記の紹介により、匿名関数式、すなわちfuncという属性に格納されているのは、新規作成であることが分かります.
      匿名関数式を作成します.
      すべての宣言の匿名関数は新しい関数です.
      したがって、最初のfunc関数は2番目のfunc関数とは異なり、新しく作成された関数です.
  •   関数式の内部は、現在の関数を格納する変数にアクセスできますか?
  •   オブジェクト内部の関数式:
  • var o={
        fn:function (){
            console.log(fn);
        }
    };
    
    o.fn();//ERROR  
         2.    非オブジェクト内部の関数式:
    var fn=function (){
        console.log(fn);
    };
    
    fn();//function (){console.log(fn);};  
        
      結論は、varまたは非オブジェクト内部の関数表現を使用すると、現在の関数を格納する変数にアクセスできます.オブジェクト内部でのアクセスはできません.
      その理由も非常に簡単です.関数の作用によるドメインチェーンの問題で、varを採用したのは外部でfn変数を作成しました.関数の内部はもちろん内部でfnを見つけられません.
      上巻作用領域はfnを検索しますが、オブジェクト内部を作成する際には、関数機能領域内でfnを作成していないため、アクセスできません.
      したがって、上記のように、最も内側の層のreturnから出るfunc関数は、第二層func関数ではなく、最も外側の層のfunc関数であることが分かります.
      ですから、三つのfun関数の関係もはっきりしました.一番目は三番目に等しく、二番目にも等しくないです.
  • はどの関数を呼び出していますか?
  •   もとの問題を見て、今プログラムの中に二つのfunc関数があると分かりました.次の問題は分かりました.運行時に彼が実行したのはどのfuncですか?
      関数
          1.   最初の行a
    var a = func(0);
    a.func(1);
    a.func(2);
    a.func(3);
    
    
    
    
    /* a.func(1)     //   func(n=0,o=undefined)!!!!!!              
     
    a.func(m=1)→   →func(n=1,o=0)→n   1,o   0.
    var a={
        func:  console.log(0),  :{
            func:function(1){
                return func(m,1)    //        n     undefined,o      1
            }
        }
    }   */
    
    
    /* a.func(2)    //   func(n=0,o=undefined)!!!!!!              
     
    a.func(m=2)→   →func(n=2,o=0)→n   2,o   0.
    var a={
        func:  console.log(0),  :{
            func:function(2){
                return func(m,2)        n     undefined,o      2
            }
        }
    }     */
    
       a.func(3)
      最初のfunc(0)は、第1層fun関数を呼び出していることが分かる.二つ目のfunc(1)は前のfunの戻り値を呼び出すfunc関数です.
      後の幾つかのfunc(1),func(2),func(3),関数は第二層fun関数を呼び出しています.
      すなわち、
      初めてFnc(0)を呼び出すと、oはundefinedとなります.
      2回目のfunc(1)の呼び出しはmが1であり、このときfuncは外層関数のnを閉じています.すなわち、初めて呼出されたn=0であり、m=1,n=0であり、内部で第1層funcを呼び出します.
      関数func(1,0)だからoは0です
      3回目のフルnc(2)の呼び出しはmは2ですが、依然としてa.funcを呼び出していますので、最初の呼び出し時のnを閉じています.すなわちoは0である
      第四回同理
      つまり、最終的な答えはundefinedで、0,0,0
           2.   2行目b
    var b = func(0).func(1).func(2).func(3);//undefined,0,1,2
     
    /*   func(n=undefined,o=undefined)*/
    /*
        var b = func(n=0,o=undefined);    ,         n o.
          console.log(undefined),  :
        var b={
            func:  func(n=1,o=0);console.log(0),  :{
                func:  func(n=2,o=1);console.log(1),  :{
                    func:  func(n=3,o=2);console.log(2),  :{
                        func:function(3){
                            return func(m,3)        n     undefined,o      3
                        }
                    }
                }
            }
        }
    */
      まずfunc(0)から見て、きっと呼び出された第一層func関数です.彼の戻り値はオブジェクトですので、2番目のfun(1)は2番目のfunc関数を呼び出します.
      いくつかの面も呼び出しの第二層func関数です.
      すなわち、
      第1層Fnc(0)を初めて呼び出した場合、oはundefinedとなります.
      第二コール.func(1)の場合mは1で、このときfuncは外層関数のnを閉じています.すなわち、初めて呼出されたn=0で、m=1,n=0で、内部で第一層funcを呼び出します.
      関数func(1,0)だからoは0です
      3回目の呼び出し.func(2)の場合mは2です.この場合、現在のfunc関数は最初に実行したリターンオブジェクトではなく、2回目に実行したリターンオブジェクトです.そして、2回目に実行します.
      第一層func関数は、時々(1,0)ですので、n=1,o=0は、戻るときは第二回のnを閉じ、第三層fun関数を3回目に呼び出したときはm=2,n=1、すなわち第一層funcを呼び出します.
      関数func(2,1)ですので、oは1です.
      第四回呼び出し.func(3)の場合mは3で、第三回呼び出しのnを閉じて、同じ道理で、最終的に第一層func関数を呼び出します.だからoは2です
      つまり最終的な答えです.undefined、0、1、2
            3.   3行目c
    var c = func(0).func(1);  c.func(2);  c.func(3);
      前の二つの例によれば、
      fun c(0)は第一層func関数を実行するために、func(1)はfunc(0)が戻ってくる第二層fun関数を実行します.ここで文が終わり、そこでcはfunc(1)の戻り値が格納されます.
      func(0)の戻り値ではないので、cではパケットを閉じるのもfunc(1)が2回目に実行するnの値です.c.func(2)は、func(1)が戻る第2層func関数を実行し、
      c.func(3)が実行するのも、func(1)が戻ってくる第二層func関数である.
      すなわち、
      第1層Fnc(0)を初めて呼び出した場合、oはundefinedとなります.
      第二コール.func(1)の場合mは1で、このときfuncは外層関数のnを閉じています.すなわち、初めて呼出されたn=0で、m=1,n=0で、内部で第一層funcを呼び出します.
      関数func(1,0)だからoは0です
      3回目の呼び出し.func(2)の場合mは2であり、このときfuncは2回目の呼び出しn=1であり、m=2,n=1であり、1階のfunc関数func(2,1)を内部で呼び出します.
      だからoは1です
      第4回.func(3)の場合は同じですが、呼び出しの2回目の戻り値となり、最終的には1階のfunc関数func(3,1)を呼び出しますので、oはまだ1です.
      つまり最終的な答えです.undefined、0、1、1