javascriptのthisの針-11

21086 ワード

前言
「javascriptの実行環境-08」では、JavaScriptコードが実行可能なコードを実行すると、対応する実行コンテキストが作成されます.各実行コンテキストには、3つの重要な属性があります.
  • 変数オブジェクト(Varable oject,VO)
  • 作用ドメインチェーン
  • this
  •   JavaScript中のthisは他の言語とは少し違っています.例えば、Java .net言語のthisはコードの実行段階では可変ではなく、JavaScriptのthisは呼び出し段階でバインディングされています.また、この性質がthisに大きな柔軟性を与えたからである.すなわち、関数が異なる呼び出し方式であれば、thisの値が異なる可能性がある.
    定義
    thisオブジェクトは、動作時に環境バインディングを実行する関数に基づいて、ステートメントの位置よりも関数の呼び出し位置に関係します.thisは、関数呼び出し段階におけるバインディング、すなわちコンテキスト作成を実行する段階において割り当てられ、変数オブジェクトに保存されていると理解できる.
    4つのバインディング規則
    newコンストラクタバインド、thisは新しく作成されたオブジェクトを指します.
     1 function createPerson(){
     2        return new person();
     3     }
     4     function person() {
     5         this.name = "Joel";
     6         this.say=function(){
     7             console.log(p)
     8             console.log('hello' + this.name)
     9         }
    10     }
    11     var p = new person();
    12     p.say();
    13     console.log(p.name);//Joel
    14     console.log('  ')
    15     var t=createPerson();
    16     t.say();
    直接newであろうと、function createPerson関数で帰ってくるオブジェクトであろうと、thisは新しく作成されたオブジェクトを指します.
    バインディングを表示します.thisは、オブジェクトを転送する方向を指します.
     1     //call() apply() bind()     
     2     window.color = "red";
     3     var Obj = { color: "blue" };
     4     function sayColor() {
     5         console.log(this.color);
     6     }
     7     sayColor();// red this window
     8     sayColor.call(this);//red
     9     sayColor.call(window);//red
    10     sayColor.call(Obj);// blue  this      Obj
    11     sayColor.apply(Obj);//blue  this      Obj
    12     sayColor.bind(Obj)();//blue  this      Obj
    null/undefinedをthisのバインディングオブジェクトとしてcall/apply/bindに入れば、これらの値は呼び出し時に無視されます.実際に使うのはデフォルトのバインディングルールです.
    1   function foo() {
    2       console.log(this.a)
    3     }
    4    var a=2;
    5     foo.call(null);//2
    6     foo.call(undefined);//2
    隠士結合
    オブジェクトの形で呼び出し、thisは現在のオブジェクトを指します.
     1    function foo(){
     2         console.log(this)//{a: 2, name: "Joel", foo: ƒ}
     3         console.log(this.a)//2
     4     }
     5     var obj={
     6         a:2,
     7         name:'Joel',
     8         foo:foo
     9     };
    10     obj.foo();
    この場合、thisは現在のobjオブジェクトを指しますが、書き方を変えるとthisが失われます.
     1     function foo(){
     2         console.log(this)//{a: 2, name: "Joel", foo: ƒ}
     3         console.log(this.a)//2
     4     }
     5     var obj={
     6         a:2,
     7         name:'Joel',
     8         foo:foo
     9     };
    10     obj.foo();
    11     //this      
    12     var t= obj.foo;
    13     t(); //window undefined
    変数tはこの時保存されています.関数の参照はobjとは関係がないので、ここでthisはwindowを指します.
    デフォルトのバインディングの厳密なモードでは、thisはundefinedにバインドされます.そうでないと、グローバルオブジェクトwindowにバインドされます.
     1   function foo(){
     2         console.log(this)//window
     3         console.log(this.a)//Joel
     4     }
     5     var a='Joel';
     6     foo();
     7 
     8     //    
     9     function fo(){
    10         'use strict'  //    
    11         console.log(this)//undefined
    12         console.log(this.b)//   Cannot read property 'b' of undefined
    13     }
    14     var b='Joel';
    15     fo();
    以上は基本的なthisバインディング規則であり、new、バインディングが容易であることを示しています.ここでは、デフォルトのバインディングは匿名関数、クローズド、関数をパラメータとしてバインディングしていると誤解しやすいです.
    独立呼び出し:thisはwindowを指します.
     1   var name='Joel',age=12;
     2     function say(){
     3         function say1(){
     4             console.log(this.name);//window
     5             function say2(){
     6                 name+='-l'
     7                 console.log(this.name);//window
     8             }
     9             say2()
    10         }
    11         say1();
    12     }
    13     say();
    14 
    15     //    
    16     (function(){
    17        console.log(this.name)
    18     })()
    functionをパラメータとして伝えることは、独立して呼び出すのと同じ原理です.
     1 function foo() {
     2         console.log(this)//window
     3         console.log(this.a)//oops global
     4     }
     5     function doFoo(fn) {
     6         console.log(this);//window
     7         fn();//    foo()
     8     }
     9     var obj = {
    10         a: 2,
    11         foo: foo
    12     }
    13     var a = 'oops global';
    14     doFoo(obj.foo);
    同じ理由でsetTimeoutも同じです.
     1  var obj = {
     2         a: 2,
     3         foo: function() {
     4             console.log(this); 
     5         },
     6         foo2: function() {
     7             console.log(this);   //this    obj 
     8             setTimeout(this.foo, 1000);   // this    window 
     9         }
    10     }
    11     var a = 'oops global';
    12     obj.foo2();
    クローズド中のthis
     1     var name = "Joel";
     2     var obj = {
     3         name: "My object",
     4         getName: function() {
     5             // var that = this;   //  getNameFunc() this   that   
     6             return function() {
     7                 return this.name;
     8             };
     9         }
    10     }
    11     console.log(obj.getName()());   // "Joel"
    ここではオブジェクトの方法でObj.get Name()を呼び出しますが、getNameのthisはObjを指していますが、戻ってくる匿名関数の中のthisはなぜwindowですか?
    最後の文を二つのステップに分解して実行します.
    1 var t=obj.getName();
    2 t();
    独立して呼び出しているような感じがしますか?Objのnameにアクセスする必要があれば、thisオブジェクトをキャッシュするだけで、匿名関数にアクセスすることができます.var that=this;注釈を取ればいいです.
    締め括りをつける
  • thisは変数オブジェクトの属性の一つで、呼び出し時にバインディングされたもので、ステートメントの位置より関数の呼び出し位置に関係します.
  • 呼び出し位置を見つけ、バインディング規則に従ってthisバインディングを分析する.
  • デフォルトのバインディング厳格モードでは、thisはundefinedにバインドされ、そうでないとグローバルオブジェクトwindowにバインドされます.
  • 思考問題
     1     var length = 5;
     2     var obj = {
     3         foo: function (fn) {
     4             console.log(this.length); // this => obj
     5             fn(); // this => window
     6             arguments[0](); // this => arguments
     7             var bar = arguments[0];
     8             bar(); // this => window
     9         },
    10         length: 10
    11     }
    12     var fn = function () {
    13         console.log(this.length);
    14     }
    15     obj.foo(fn);
    16     //10, 5, 1, 5