JavaScriptの中でargmentsとthis対象の用法は分析します。


本論文の実例はJavaScriptにおけるargmentsとthisオブジェクトの使い方を述べている。皆さんに参考にしてあげます。具体的には以下の通りです。
関数の内部には二つの特殊なオブジェクトがあります。
1、アーグメンント対象
js関数は、どれぐらいのパラメータを定義しても構いません。つまり、定義された関数が2つのパラメータだけを受信しても、呼び出し時に2つのパラメータが伝達されるとは限りません。jsの関数パラメータは内部で1つの配列で表されています。関数内では、argmentsオブジェクトを通じてこのパラメータ配列にアクセスできます。したがって、ネーミングパラメータは、js関数によって明示的に使用されなくてもよい。
関数が呼び出されると、着信したパラメータはargmentsクラスの配列オブジェクトに保存され、argmentsを介してすべての関数にアクセスでき、呼び出されたときにそのパラメータリストに渡されます。
argmentsは、各要素に対して四角括弧文法でアクセスでき、length属性を持っていますが、すべての配列方法が欠けていますので、本当の配列ではありません。
アーグメンントを使用すると、求和関数が実現されます。

function add() {
 var sum = 0;
 for (var i = 0, len = arguments.length; i < len; i++)
  sum += arguments[i];
 return sum;
}

アーグメンントの主な用途は保存関数パラメータですが、このオブジェクトにはもう一つのcalee属性があります。この属性はポインタで、このアーグメンツオブジェクトを持つ関数を指します。arguments.callee属性を使用して、階乗関数を実現できます。

function factorial(num) {
  if (num <= 1)
  return 1;
  else
  return num * arguments.callee(num - 1);
}

注意:
厳密なモードでは、arguments.callee属性を使用することはできません。また、argmentsオブジェクトに値を割り当てることもできません。さらに、argmentsオブジェクトでパラメータの変化を追跡することはできません。
同じ効果を達成するためにネーミング関数式を使用できます。

var factorial = (function func(num) {
 if (num <= 1)
  return 1;
 else
  return num * func(num - 1);
));

js関数には署名がないので、js関数は再負荷されていません。同じ名前の関数の場合、先に定義された関数が上書きされます。もちろん,導入されたパラメータの種類と数を調べて異なる反応をすることで,方法の荷重を模倣することができる。
2、thisオブジェクト
他の言語と違って、JavaScriptのthisはいつも一つのオブジェクトを指していますが、具体的にはどのオブジェクトが実行時の関数に基づいて環境動的バインディングを実行していますか?
  • thisは、コンテキストに入るときに決定され、コンテキスト実行中に恒久的に変化しないコンテキストを実行する属性である。
  • thisは動的に結合されたものであり、すなわち運転中にバインディングされているものである。
  • thisは、グローバルオブジェクトであってもよく、現在のオブジェクトまたは任意のオブジェクトは、関数の呼び出しに依存します。関数の呼び出し方法には、一般的な関数として呼び出され、オブジェクト方法として呼び出され、構築関数として呼び出され、call()およびapply()を使用して呼び出されます。
  • (1)通常関数として呼び出す
    関数がオブジェクトの属性として呼び出されない場合、すなわち呼び出された場合、thisはグローバルオブジェクトに紐付けされます。ブラウザのJavaScriptでは、このグローバルオブジェクトはwindowオブジェクトです。
    
    var name = "Alice";
    function getName (name) {
     return this.name;
    }
    alert(getName()); //   :Alice
    var name = "Alice";
    var obj = {
     name: 'Bruce',
     getName: function(name) {
      return this.name;
     }
    };
    var getName = obj.getName();
    alert(getName()); //   :Alice
    
    
    以上の2つの例では、thisはすべてグローバルオブジェクトにバインドされている。
    
    var firstname = "A";
    var lastname = "B";
    var person = {
     firstname : "Alice",
     lastname : "Bruce",
     setName : function(firstname, lastname) {
      var setFirstName = function(firstname) {
       this.firstname = firstname;
      };
      var setLastName = function(lastname) {
       this.lastname = lastname;
      };
      setFirstName(firstname);
      setLastName(lastname);
     }
    };
    person.setName("Cindy", "David");
    alert(firstname);//Cindy
    alert(lastname);//David
    alert(person.firstname);//Alice
    alert(person.lastname);//Bruce
    
    
    問題:関数の内部で定義された関数は、thisが大域を指すこともありますが、内部関数のthisが外部関数に対応するオブジェクトに結合されることが望ましいです。
    理由:内部関数が外部関数のthis変数に直接アクセスすることは永遠に不可能です。
    解決:外部関数体で内部関数に入るときに、thisを変数に保存して、この変数を使います。
    
    var firstname = "A";
    var lastname = "B";
    var person = {
     firstname: "Alice",
     lastname: "Bruce",
     setName: function(firstname, lastname) {
      var that = this;
      var setFirstName = function(firstname) {
       that.firstname= firstname;
      };
      var setLastName = function(lastname) {
       that.lastname= lastname;
      };
      setFirstName(firstname);
      setLastName(lastname);
     }
    };
    person.setName("Cindy", "David");
    alert(firstname);//A
    alert(lastname);//B
    alert(person.firstname);//Cindy
    alert(person.lastname);//David
    
    
    (2)オブジェクトメソッドとして呼び出す
    関数がオブジェクトメソッドとして呼び出されると、thisは現在のオブジェクトにバインドされます。
    
    var firstname = "A";
    var lastname = "B";
    var person = {
     firstname : "Alice",
     lastname : "Bruce",
     setName : function(firstname, lastname) {
      this.firstname = this.firstname + firstname;
      this.lastname = this.lastname + lastname;
     }
    };
    person.setName("Cindy", "David");
    alert(firstname);//A
    alert(lastname);//B
    alert(person.firstname);//AliceCindy
    alert(person.lastname);//BruceDavid
    
    
    
    thisは現在のオブジェクト、すなわちpersonオブジェクトにバインドされています。
    (3)コンストラクタとして呼び出す
    JavaScriptにはクラスがありませんが、コンストラクタからオブジェクトを作成することができます。また、new演算子を提供して、コンストラクタを一つのクラスに見えるようにします。
    構造関数を使って新しいオブジェクトを作成すると、関数のthisが全体に向けられないように、新たに作成されたオブジェクトにthisを向けることができます。
    
    var name = "Alice";
    function Person(name) {
     this.name = name;
    }
    var person = new Person("Bruce");
    alert(name);//Alice
    alert(person.name);//Bruce
    
    
    構造関数を用いて新しいオブジェクトpersonを作成し、thisはpersonを指します。
    newでコンストラクタを呼び出す時。もう一つの問題に注意したいのですが、もしコンストラクタがobjectタイプのオブジェクトを明示的に返したら、コンストラクタが返した結果はこのオブジェクトであり、thisではありません。
    
    function Person() {
     this.name = "Alice"
     return {
      name: "Bruce"
     }
    }
    var person = new Person();
    alert(person.name);//Bruce
    
    
    (4)コール()とアプリ()呼び出しcall()およびapply()は、関数が実行するコンテキスト環境、すなわちthisバインディングのオブジェクトを切り替える。thisはapply()call()の最初のパラメータを指します。
    
    function Person(name) {
     this.name = name;
     this.setName = function(name) {
      this.name = name;
     }
    }
    var person1 = new Person("Alice");
    var person2 = {"name": "Bruce"};
    alert("person1: " + person1.name); // person1: Alice
    person1.setName("David");
    alert("person1: " + person1.name); // person1: David
    alert("person2: " + person2.name); // person2: Bruce
    person1.setName.apply(person2, ["Cindy"]);
    alert("person2: " + person2.name); // person2: Cindy
    
    
    apply()は、person 1の方法をperson 2に適用し、thisもperson 2に結合される。
    3、this優先度
    (1)関数がnewで呼び出されたかどうか、はい、新規作成されたオブジェクトにthisが紐付けられます。
    (2)関数がコール、appyで呼び出されたかどうか、はい、指定されたオブジェクトにthisが紐付けられます。
    (3)関数はコンテキストオブジェクトで呼び出すかどうか、はい、コンテキストオブジェクトに結合されます。
    (4)全部でない場合は、デフォルトのバインディングを使用して、厳密なモードでundefinedにバインドすると、グローバルオブジェクトにバインドされます。
    4、thisがなくなった問題
    eg 1:
    
    var person = {
     name: "Alice",
     getName: function() {
      return this.name;
     }
    };
    alert(person.getName()); // Alice
    var getName = person.getName;
    alert(getName()); // undefined
    
    
    person.getName()を呼び出すと、getName()方法は、personオブジェクトの属性として呼び出されるので、thisは、personオブジェクトを指す。person.getNameを別の変数getNameで引用し、getName()を呼び出すと、通常の関数として呼び出されるので、thisはグローバルwindowを指す。
    eg 2:
    
    <div id="div">     </div>
    <script>
     var getId = function(id) {
      return document.getElementById(id);
     };
     alert(getId('div').innerText);
    </script>
    <div id="div">     </div>
    <script>
     var getId = document.getElementById;
     alert(getId('div').innerText); //     
    </script>
    
    
    問題:1段目の呼び出しは正常ですが、2段目の呼び出しは異常です。
    理由:多くのエンジンのdocument.getElementById()メソッドの内部実装にはthisが必要であり、thisが本来意図していたのはdocumentであり、最初のセグメントコードがgetElementById()メソッドでdocumentオブジェクトの属性として呼び出されたとき、メソッド内部のthisは確かにdocumentを指しています。この時は普通の関数の呼び出しとなり、関数内部のthisはwindowを指しています。元のdocumentではありません。
    解決:appyを利用してdocumentをthisとしてgetId関数に導入し、thisを修正します。
    
    <div id="div">     </div>
    <script>
     document.getElementById = (function(func) {
      return function() {
       return func.apply(document, arguments);
      };
     })(document.getElementById);
     var getId = document.getElementById;
     alert(getId('div').innerText); //     
    </script>
    
    
    もっと多くのJavaScriptに関する内容に興味がある読者は、当駅のテーマを見ることができます。「javascript対象向け入門教程」、「JavaScript常用関数技術のまとめ」、「JavaScriptエラーとデバッグテクニックのまとめ」、「JavaScriptデータ構造とアルゴリズム技術のまとめ」、「JavaScriptはアルゴリズムと技術の総括を遍歴します。」および「JavaScript数学演算の使い方のまとめ
    本論文で述べたように、JavaScriptプログラムの設計に役に立ちます。