関数のパラメータargments、現在のコンテキストthis、call apply


関数のパラメータ
jsには様々な「疑似配列」があります.例えば、argmentsやdomに関するchildNodesなど、これらのオブジェクトにはlength属性がありますが、数字でインデックス要素を表示することもできます.しかし、それらはArayオブジェクトではなく、Objectオブジェクトです.これらのconstruct属性からはっきりと判断できます.
javascriptは関数のパラメータを扱う時、他のコンパイル型の言語と違っています.javascriptでは、インタプリタが関数に伝達するのは配列に似た内部値で、アーグメンツといいます.これは関数オブジェクトが生成される時に初期化されます.まず一例を通してこの不思議なargmentsを討論します.
function sum(){
    var len = arguments.length
    for(var i=0; i<len; i++){
        alert(arguments[i]); //  arguments   
    }

    var result = 0;   
    for(var i=0; i<len; i++){   
       var current = arguments[i];   
       if(isNaN(current)){
           throw new Error("not a number exception");   
       }else{  
           result += current;   
       }
    }
    return result;   
}
sum(); //  sum   ,arguments    ,arguments.length=0
sum(10, 20, 30, 40); //  arguments.length=4       100
sum(4, 8, 15, 16, 23, 42);//  arguments.length=6   108
sum("new");//  arguments.length=1    Error: not a number exception
運転結果から、関数sumは明示的な形の参を定義していないが、任意の多くのパラメータに動的に伝達することができます.sum関数では、これらのパラメータをどのように参照しますか?ここではargmentsという対象を使う必要があります.
もう一つの例を見ます
function f(x,y){
    alert(x+"   ===   "+y);
    var len = arguments.length
    for(var i=0; i<len; i++){
        alert(arguments[i]); //  arguments  
    }
}
f(1); 
f(1,2);
f(1,2,3); 
//      :                    ,            arguments       
//        a   ,         ,  a arguments[0]           ,       ,          
function change(a){
    alert(a);   //     a gerry,  alert  gerry;        alert undefined
    arguments[0]='xiaoxiaozi';   // arguments[0]         
    alert(a);    //  ,      xiaoxiaozi
}
//    :n*(n-1)*(n-2)*...*3*2*1   
function factorial(n){ 
    if(n == 1){   
        return 1;   
    }else{   
        return n * factorial(n - 1);   
    }   
}
//      :
function factorial(n){   
    return n==0 ? 1 : n * factorial(n-1);     
}  
//    :
(function(x){   
  return x == 0 ? 1 : x * arguments.callee(x-1);   
})(10);//3628800  
  ,arguments.callee      ,       。caller    
callee :        Function   ,        Function      。 
caller :          ,          。       
現在のコンテキストthis、call apply
方法自体は関数ですが、方法の使用は制限されています.
各オブジェクトには0つ以上の属性が含まれており、属性は任意のタイプであってもよく、もちろんオブジェクトも含まれています.関数自体はオブジェクトですので、一つの関数をオブジェクトに入れることができます.この関数はオブジェクトの一つの方法になります.その後、この方法を用いると、オブジェクト名に「.」の操作子を利用して実現することができる.
メソッドの呼び出しにはオブジェクトのサポートが必要ですが、方法ではオブジェクトをどう取得しますか?thisthisキーワードは、この方法のオブジェクトを呼び出すという意味で、オブジェクトの呼び出し方法によって、thisキーワードがそのオブジェクトに向けられます.たとえば:
domObj.onclik=function(){
    clickFun(this)/onclickは対象domObjの方法ですので、ここのthisはdomObjです.
)
javascriptでは、thisは、現在のコンテキスト、すなわち、使用者の引用(thisは、方法の使用者(オブジェクト)に対する参照を表している)を表している.thisの値は、関数がどのように宣言されているかではなく、どのように関数が呼び出されているかによって決まるのです.これは従来のオブジェクト指向言語とは違います.関数の文脈は変化することができますので、関数内のthisも変化することができます.関数はオブジェクトとしての方法もありますし、別のオブジェクトとしての方法もあります.つまり、thisは任意のオブジェクトとfunction要素を結合するときの概念だけで、関数自体は独立しています.関数のコンテキストは、Functionオブジェクトのcallまたはappy関数によって変更できます.
call apply Function    ,            ,    this       call  apply      ,  :
var name = "the name of window";//        ,name
var jack = {   //     ,   jack
    name : "jack",   
    age : 26   
}
var gerry = {  //      ,   gerry
    name : "gerry",   
    age : 25   
}
function printName(){  //           
    return this.name;   
}   
    
//  printName     jack,    this jack   
alert(printName.call(jack));   
//  printName     gerry,   this gerry
alert(printName.call(gerry));   
//  printName     window,   this window,  "the name of window"
alert(printName.call(window));
//      ,   :  window   printName  。  window          ,    window  ,    。   "the name of window"
printName();
 
//  apply  :
alert(printName.apply(jack));   
alert(printName.apply(gerry));  
 
         call apply         ,        ,apply                     , call         ,       (,)  :
setName.apply(jack, ["tom"]);   
alert(printName.apply(jack));   //  tom
    
setName.call(gerry, "gerry wang");   
alert(printName.call(gerry));  //  gerry wang
参考:
http://abruzzi.iteye.com/ブログの中の「javascriptカーネルシリーズ」