JavaScriptのthis、callとappy

5030 ワード

ここをクリックして私のgithubを訪問してもっと詳しいことを知ります.
JavaScript学習において、thisの重要性は不明であり、深く勉強する必要があります.thisと関連している二つの特別な注意が必要なのはcall、appyです.本編ではthisから説明し、call、appyの使い方を紹介します.
関数を呼び出したときに、コード実行制御権はこの関数に移ります.パラメータはこの関数に伝えられます.関数を宣言する時に定義される形式パラメータ以外に、各関数は2つの追加パラメータを受け取ります.thisとargments.
this
JavaScriptのthisは常にオブジェクトを指しています.このオブジェクトは関数実行時の環境動的バインディングに基づいています.関数宣言時の環境ではありません.
実行環境については、本シリーズのJavaScriptの作用域と作用域チェーンを参照してください.
this指向
this指向問題については、関数呼び出しと密接に関係しており、大きく四つの種類に分けられます.
  • (1).メソッドコール.オブジェクトとして呼び出す方法です.
  • (2)関数コールすなわち、一般関数として呼び出されます.
  • (3).コンストラクタ機能呼び出し.つまりnewで呼び出します.
  • (4).callとappy呼び出し;Function.prototype.callまたはFuntions.prototype.appyで呼び出します.
  • .メソッド呼び出し
  • 
        var obj = {
            name: 'Job',
            getName: function() {
                console.log(this === obj); //  true
                console.log(this.name);  //  Job
                return this.name;
            }
        };
        obj.getName();
    
    関数をオブジェクトとする方法が呼び出されると、thisは常にオブジェクトを指す.
  • .関数呼び出し
  • 
        var name = 'Job';
        var getName = function() {
            console.log(this === window);  //  true
            console.log(this.name);  //  Job
            return this.name;
        };
        getName(); //      
    
    厳密でないモードでは、関数が一般的な関数として呼び出されると、この関数が呼び出されたときに実行される環境に関係なく、thisは常にグローバルオブジェクトを指し、JavaScriptではwindowオブジェクトとなります.
    次の例を見て、理解を深めます.
    
        
            var id = 'windowId';
            document.getElementById('myDiv').onclick = function() {
                console.log(this.id); //  myDiv
                var fn = function() {
                    console.log(this.id); //  windowId
                };
                fn(); //      
            };
        
    
  • .コンストラクタ機能呼び出し
  • 
        var Animal = function(name) {
            this.name = name;
        };
        var animal = new Animal('Dog');
        console.log(animal.name); //  Dog
    
    newでコンストラクタ関数を呼び出すと、いずれもオブジェクトに戻ります.このオブジェクトはコンストラクタ関数の一例として見られます.一般的に、コンストラクタ内のthisはこのオブジェクトを返します.しかし、コンストラクタがオブジェクトを明示的に返す場合、
    
        var Animal = function(name) {
            this.name = name;
            return {
                name: 'Job'
            };
        };
        var animal = new Animal('Dog');
        console.log(animal.name); //  Job    
    
    このとき、thisはコンストラクタが明示的に返したオブジェクトを指します.
  • 4.calとappy呼び出し
  • 
        var obj = {
            name: 'Job',
            getName: function() {
                console.log(this === obj); 
                console.log(this.name);  
                return this.name;
            }
        };
        var obj2 = {
            name: 'Web'
        };
        console.log(obj.getName());  //  Job
        console.log(obj.getName.call(obj2)); //  Web
        console.log(obj.getName.apply(obj2)); //  Web
    
    関数をFuntions.prototype.callまたはFuntions.prototype.applyで呼び出すと、動的着信パラメータが実行環境を変更し、このときthisは着信するオブジェクトを指します.
    callとappy
    callとappyはFunctionのプロトタイプで定義された2つの方法で、広く使われています.
  • .calとappyの違い
  • 両者の作用は全く同じで、異なるところは着信パラメータの形式にある.
    call着信パラメータの数は固定されていません.最初のパラメータは呼出関数の体内のthisの指向を表し、その後、呼出関数に必要なパラメータを順次表します.
    applyは最大2つのパラメータを受け取り、最初のパラメータは関数内のthisの指向を指定し、第二のパラメータは下付きのセットであり、配列またはクラスであり、パラメータとして呼び出された関数に伝えられます.
    
        var fn = function(a, b, b) {
            console.log([a, b, c]);
        };
        fn.call(null, 1,2,3);
        fn.apply(null, [1,2,3]);
    
    厳密でないモードでは、callまたはapplyを使用する場合には、最初のパラメータが必要であり、最初のパラメータがnullに入ったときには、関数内のthisは、オブジェクトを含む呼び出された関数の宿主オブジェクトを指します.厳しいモードでは、thisはnullを指します.
  • .callとappyのアプリケーション
  • (1)thisを変更すると、コールまたはappy呼び出し関数を使用して、関数の内部のthisの方向を変更することができます.実例は前の文のように、関連例を指す.
    (2).Function.prototype.bind Function.prototype.bindは、関数の内部にあるthis指向性を結合するために使用することができ、そのパラメータはthisの指向性オブジェクトである.IE 8及び以下はサポートしていません.ここでは自分で一つを実現できます.
    
        Function.prototype.bind = function(context) {
            var self = this;  //        
            return function() { //       
                return self.apply(context, arguments); //              this     
            };
        };    
        var obj = {
            name: 'Job'
        };
        var fn = function() {
            console.log(this.name);
        };
        fn.bind(obj)();
    
    (3)他のオブジェクトを借りる方法で最も熟知しているのは、構造関数を借りて類似の継承効果を実現することです.
    
        var Animal = function(name) {
            this.name = name;
        };
        var Dog = function() {
            Animal.apply(this, arguments);
        };
        Dog.prototype.getName = function() {
            return this.name;
        };
        
        var dog = new Dog('Dog');
        console.log(dog.getName());  //  Dog
    
    もう一つのよくある場合は、Aray.prototypeオブジェクト上の方法を借りて関数パラメータクラスの配列argmentsを処理することです.
    
        (function() {
            Array.prototype.shift.call(arguments); //arguments    [1,2,3]
            var args = Array.prototype.slice.apply(arguments); // arguments              args  
            console.log(arguments); //  [2, 3]
            console.log(args); //  [2, 3]
        })(1,2,3);
    
    Aray.prototype上のshift方法を借りて、パラメータリストのトップを削除します.もちろん、他の方法を借りて、push、sliceなどの目的を達成することもできます.
    JavaScriptの中で、callとappyの応用は非常に広範で、各種Jsフレームバンクの中で、すべてその影を発見するのは難しくありません.