javascriptシリーズのthisまとめ

7143 ワード

参照リンク:https://github.com/jawil/blog...
JavaScriptでは、thisは現在の関数で実行されているコンテキスト環境を指します.
  • 関数呼び出し
  • メソッド呼び出し
  • 構築関数呼び出し
  • 間接呼び出し
  • バインディング関数呼び出し
  • 矢印関数
  • 場面を間違えやすい
  • 関数の呼び出し
    関数コールは、ペアの引用符で受信した関数を表しています.カンマで区切られた異なるパラメータからなる表現です.
    関数コール中のthis
        function sum(a, b) {  
          console.log(this === window); // => true
          this.myNumber = 20; //          'myNumber'   
          return a + b;
        }
        // sum()      
        // this   sum()        (window)
        sum(15, 16);     // => 31  
        window.myNumber; // => 20
    sum(15,16)が起動されると、JavaScriptは自動的にグローバルオブジェクト、すなわちwindowにthisを設定します.
    厳密モードでは、関数呼び出し中のthis
    厳格なモードはECMAScript 5.1によって導入され、JavaScriptのいくつかの異常処理を制限するために使用され、より良い安全性とより強いエラーチェックメカニズムを提供します.厳密なモードを使うと、関数体の上に'use strict'を置くだけです.このように、コンテキスト環境のthisをundefinedに変えることができます.このようにコンテキスト環境を実行するのは、グローバルオブジェクトではなく、非厳格モードとは逆です.
        function multiply(a, b) {  
          'use strict'; //       
          console.log(this === undefined); // => true
          return a * b;
        }
        //            multiply() 
        // this   multiply()    undefined
        multiply(2, 5); // => 10
    厳密なモードは現在の作用領域だけでなく,内部作用領域,すなわち内部宣言のすべての内部関数の役割領域にも影響を及ぼします.
        function execute() {  
          'use strict'; //       
          function concat(str1, str2) {
            //           
            console.log(this === undefined); // => true
            return str1 + str2;
          }
          //          concat()
          // this   concat()    undefined
          concat('Hello', ' World!'); // => "Hello World!"
        }
        execute();  
    メソッドの呼び出し
    一つのオブジェクトでメソッドを呼び出すと、thisはオブジェクト自体を表します.厳密なモードは現在の作用領域だけでなく,内部作用領域,すなわち内部宣言のすべての内部関数の役割領域にも影響を及ぼします.
        var calc = {  
          num: 0,
          increment: function() {
            console.log(this === calc); // => true
            this.num += 1;
            return this.num;
          }
        };
        //     ,this    calc
        calc.increment(); // => 1  
        calc.increment(); // => 2       
    コンストラクタ呼び出し
        function Foo () {  
          console.log(this instanceof Foo); // => true
          this.property = 'Default Value';
        }
        //       
        var fooInstance = new Foo();  
        fooInstance.property; // => 'Default Value'    
    間接呼び出し
    間接的な呼び出しは、関数が使用されたときに表示されます.コール()または.call()と.appy()は、現在起動されているコンテキスト環境を設定するために使用されます.
        var rabbit = { name: 'White Rabbit' };  
        function concatName(string) {  
          console.log(this === rabbit); // => true
          return string + this.name;
        }
        //     
        concatName.call(rabbit, 'Hello ');  // => 'Hello White Rabbit'  
        concatName.apply(rabbit, ['Bye ']); // => 'Bye White Rabbit'     
    二つの方法の最も主要な違いは.call()がパラメータのセットを受信することであり,一方.appy()は一連のパラメータをクラスの配列オブジェクトとして伝達することである.
    バインディング関数呼び出し
    バインディング関数呼び出しは,関数を一つのオブジェクトに結びつけることで,元の関数として使用した.
    方法.bind(thisArg[,arg 1[,arg 2]])は、最初のパラメータthisArgをバインディング関数として実行時のコンテキスト環境として受信し、パラメータのセットarg 1,arg 2,...を、インフォーマ関数として受信する.これは新しい関数を返して、thisArgを結合しました.
        function multiply(number) {  
          'use strict';
          return this * number;
        }
        //       ,     2
        var double = multiply.bind(2);  
        //       
        double(3);  // => 6  
        double(10); // => 20   
        var numbers = {  
          array: [3, 5, 10],
          getNumbers: function() {
            return this.array;    
          }
        };
        //         
        var boundGetNumbers = numbers.getNumbers.bind(numbers);  
        boundGetNumbers(); // => [3, 5, 10]  
        //         
        var simpleGetNumbers = numbers.getNumbers;  
        simpleGetNumbers(); // => undefined              
    ビnd()は永遠のコンテキストチェーンを作成しました.変更できません.一つの結合関数が使用されても、call()または.appy()が他の異なるコンテキスト環境に入ってきても、それ以前に接続されたコンテキスト環境は変更されず、再結合も何の役割も果たしません.
        function getThis() {  
          'use strict';
          return this;
        }
        var one = getThis.bind(1);  
        //       
        one(); // => 1  
        //    .apply()   .call()     
        one.call(2);  // => 1  
        one.apply(2); // => 1  
        //     
        one.bind(2)(); // => 1  
        //              
        new one(); // => Object  
    補助ビンの使い方
    bind()のもう一つの最も簡単な使い方は、関数が予め設定された初期パラメータを持つようにすることである.これらのパラメータ(ある場合)は、bind()の2番目のパラメータとして、this(または他のオブジェクト)の後に挿入されます.その後、ターゲット関数のパラメータリストの開始位置に挿入され、バインディング関数に渡されるパラメータはそれらの後に付いてきます.
        function list() {
          return Array.prototype.slice.call(arguments);
        }
        
        var list1 = list(1, 2, 3); // [1, 2, 3]
        
        // Create a function with a preset leading argument
        var leadingThirtysevenList = list.bind(undefined, 37);
        
        var list2 = leadingThirtysevenList(); // [37]
        var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]  
    矢印関数
    矢印関数の設計意図は、関数を簡単に作成し、定義時のコンテキスト環境をバインドすることです.
    矢印関数は、定義時の外部関数に依存するように、自身が実行するコンテキストを作成しません.
        class Point {  
          constructor(x, y) {
            this.x = x;
            this.y = y;
          }
          log() {
            console.log(this === myPoint); // => true
            setTimeout(()=> {
              console.log(this === myPoint);      // => true
              console.log(this.x + ':' + this.y); // => '95:165'
            }, 1000);
          }
        }
        var myPoint = new Point(95, 165);  
        myPoint.log(); 
    矢印関数はコンテキストを結合すると変更できません.コンテキスト変更の方法を使っても大丈夫です.
        var numbers = [1, 2];  
        (function() {  
          var get = () => {
            console.log(this === numbers); // => true
            return this;
          };
          console.log(this === numbers); // => true
          get(); // => [1, 2]
          //        .apply()   .call()
          get.call([0]);  // => [1, 2]
          get.apply([0]); // => [1, 2]
          // Bind
          get.bind([0])(); // => [1, 2]
        }).call(numbers);
    間違いやすいシーン
    thisは内部関数にあります.
        var numbers = {  
          numberA: 5,
          numberB: 10,
          sum: function() {
            console.log(this === numbers);        // => true
            function calculate() {
              console.log(this === numbers);      // => false
              return this.numberA + this.numberB;
            }
            return calculate();
          }
        };
        numbers.sum();
    解決方法:return calculate.call(this);
    thisはコールバック関数にあります.
        function Animal(type, legs) {  
          this.type = type;
          this.legs = legs;  
          this.logInfo = function() {
            console.log(this === myCat);       // => false
            console.log('The ' + this.type + ' has ' + this.legs + ' legs');
          }
        }
        var myCat = new Animal('Cat', 4);  
        setTimeout(myCat.logInfo, 1000);  
    解決方法:setTimeout(myCat.logInfo.bind(myCat)、1000);
    thisを含む方法を変数に割り当てます.
        var name = "aa";
        var user = {
           name: 'hhh',
           sayName: function(){
               console.log(this.name);
           }
       }
       var test = user.sayName;
       test();   // aa 
    解決方法:var test=user.sayName.bind;
    参照リンク
    JavaScript Thisの謎