『JavaScript入門学習』のthis問題

5521 ワード

初心者のJavaScript白として、多くのブログを見てthisに言及しました.特にthisの指向はダイナミックです.関数の呼び出しによって変化します.また、作用領域に関わる問題があります.手動でthisの方向を指定したり、変更したりすることもできます.そんなに簡単ではないようです.ちょっと調べなければならないような気がします.
一番簡単な印刷から:
//     
console.log(this); // [object Window]
//         this   undefined
'use strict';
console.log(this); // undefined
便利さのために、以下の議論は、非厳格モードの場合、すなわちグローバル印刷this==Windowである.
以下のいくつかのテーマに分けて討論します.
var={…}対象内部のthis
var person = { 
    name: 'chengxuyuan',
    age: 26,
    eat: function() {
       alert(this.name + '  ');
    }
};
console.log(person.eat); // chengxuyuan  
eat方法はpersonがオブジェクトを探して呼び出されたので、関数内部で使用されるthisはpersonを指します.より厳密に論証するために、階層を深くします.
var person = { 
    name: 'chengxuyuan',
    age: 26,
    eat: function() {
       alert(this.name + '  ');
    },
    book: {
        name: 'one day left',
        show: function() {
             alert(this.name + ' Good!');
        }
     }
};
console.log(person.book.show); // one day left Good
personのbook属性のshow方法を呼び出して、thisはbookを指して、this.nameはone day leftに等しいです.したがって、関数内部のthisの値は、その使用者オブジェクトに関連している.もしある関数が直接呼び出されて、xx.fun()ではない場合、内部のthisはどのように指しますか?コードを続行:
var person = { 
    name: 'chengxuyuan',
    age: 26,
    play: function(){
            function swim(){
               console.log(this);
               alert(this.name + '  ');
            }
           swim();
    }
};
console.log(person.play); //  [object Window]  undefined  
swim関数内部のthisがWindowオブジェクトを指していることが分かりましたので、this.nameはundefinedです.特殊な点は、personオブジェクトがプレイ関数を呼び出して実行するときに、内部定義が完了したら、すぐに自動的に実行されます.swimという能動的な実行の関数で、内部のthisはすでにpersonの対象の勢力範囲から跳び出しました.swim関数が能動的に実行する時、その対象を呼び出すのは晦で、お父さんがいなくてお母さんがいないようです.だから内部のthisはpersonを指しません.
コンストラクタオブジェクト内部のthis
構造関数は'new+メソッド名''を利用してオブジェクトを作成します.内部のthis指向も同じ原理です.
function Person() {
        console.log(this);
        this.name = 'chengxuyuan';
        this.age = 26;
        console.log(this.name);
   }
Person(); // [object Window]  undefined
var p = new Person(); //  [object Object] chengxuyuan
私たちが単純にPerson関数を実行して、thisがWindowを指して、newを通じてオブジェクトpを作成したとき、thisはpersonというオブジェクトを指しています.もう一つ注意したいのですが、プロトタイプ属性で関数を定義する場合は内部のthisもPersonを指します.
Person.prototype.getName =  function() {
    console.log(this.name);
}
var p = new Person();
p.getName(); // chengxuyuan
関数の値を他の変数に割り当てることで、内部のthisの指向性に影響を与えます.
function Person() {
        this.name = 'chengxuyuan';
        this.age = 26;
        this.eat = function() {
          alert(this.name + '   ');
        }
 }
var p = new Person();
var eatFunc = p.eat;
eatFunc();  // undefined   
はっきりと見えて、eatはもともとpに属していたが、後に全体の対象となったeatFunを指しているので、eat内部のthisはまたWindowをダイナミックに指しています.ここまで勉強すれば、小さなまとめができます.関数の内部のthisは定義の時に決められたのではなく、呼び出された時に、コンテキストシーンによって、ダイナミックに確定されます.また、一般的には呼び出し対象を指します.注意します.次に、関数の戻り値がthisに及ぼす影響を見てもいいです.
関数の戻り値がthisの方向に及ぼす影響
直接コードにいくつかの例を見ます.
function Person() {
     this.name = 'chengxuyuan';
     return {};
 }
var p = new Person();
console.log(p.name); //undefined
コンストラクタの戻り値が空のオブジェクトの場合、thisはPersonを指しません.
function Person() {
     this.name = 'chengxuyuan';
     return function() {};
 }
var p = new Person();
console.log(p.name); //undefined
コンストラクタの戻り値が空の関数である場合、thisはPersonを指しません.
function Person() {
     this.name = 'chengxuyuan';
     return undefined;
 }
var p = new Person();
console.log(p.name); //chengxuyuan
コンストラクタの戻り値がundefinedであるとき、thisはまたPersonを指す.
function Person() {
     this.name = 'chengxuyuan';
     return 1;
 }
var p = new Person();
console.log(p.name); //chengxuyuan
コンストラクタの戻り値が1のとき、thisはまたPersonを指します.
function Person() {
     this.name = 'chengxuyuan';
     return null;
 }
var p = new Person();
console.log(p.name); //chengxuyuan
コンストラクタの戻り値がnullであるとき、thisはまたPersonを指します.
まとめてみましょう.コンストラクタがオブジェクトに戻り、関数の場合、thisは戻る特定のオブジェクト関数を指します.nullまたは他の値の場合、thisはまたそのオブジェクトを指します.
call、appy、bind関数でthisの指向を修正します.
いくつかのビジネスシーンでは、thisの指向を変更したい場合がありますが、call、appy、bindの3つの関数を利用してもいいですか?それとも上の一つは関数を他の変数に割り当てることによって、内部のthisの指向に対する影響の例です.
function Person() {
        this.name = 'chengxuyuan';
        this.age = 26;
        this.eat = function() {
          alert(this.name + '   ');
        }
 }
var p = new Person();
var eatFunc = p.eat;
eatFunc();  // undefined   
既にeat関数でeat Funncに値を付けていますが、thisはWindowを指しています.どうしてもthisをさせるならpをさす.下を見てどうしますか?
コール関数:
var eatFunc = p.eat;
eatFunc.call(p);  // chengxuyuan   
これでthisはまたpを指しました.thisの指向を変更する時、他のパラメータをeat関数に伝えることができます.
function Person() {
        this.name = 'chengxuyuan';
        this.age = 26;
        this.eat = function(a,b) {
          alert('a + b =' + a + b);
          alert(this.name + '   ');
        }
 }
var p = new Person();
var eatFunc = p.eat;
eatFunc.call(1,2);  // a+b=3  chengxuyuan   
アプリ関数:
アプリ関数も同じです.主が複数のパラメータを送る必要がある場合、パラメータ配列で受信します.
var eatFunc = p.eat;
eatFunc.apply(p,[1,2]);  // a+b=3 chengxuyuan   
bind関数:
apply関数もthis指向を修正するために使用されますが、最大の違いは彼の戻り値が新しい関数を返して使用者に受信させます.
var eatFunc = p.eat;
var bindfunc =  eatFunc.bind(p);  
bindfunc(); // chengxuyuan   
thisが匿名関数および矢印関数に起因するスコープ問題
フォローアップ.