コアJavaScript-3をクリーンアップします.this

38476 ワード

これは何ですか.
  • オブジェクト向け言語では、クラスで作成されたインスタンスオブジェクトを意味します.クラスでのみ使用する
  • Javascriptでは、これはどこでも使用できます.
  • 関数とオブジェクト(メソッド)をばらばらに区別するJavaScriptでは、実際にはこの2つをほとんど区別する機能
  • である.
    1.状況によって変わるthis
  • jsでは、これは基本的に実行コンテキストの作成時に一緒に決定される.
  • 、すなわち、これは関数を呼び出すときに決定される.値は関数の呼び出し方法に依存します.
  • グローバルスペース
  • グローバル空間では、これはグローバルオブジェクトを指します.
  • グローバルオブジェクトはjsランタイム環境とは異なる名前と情報を有し、ブラウザ環境ではグローバルオブジェクトはwindow,Nodeである.jsではglobalです.

  • グローバル変数とグローバルオブジェクト:
  • グローバル変数が宣言された場合、javascriptエンジンはグローバルオブジェクトのpropertyに割り当てられます.
  • var a = 1;
    console.log(a);        // 1
    console.log(window.a); // 1
    console.log(this.a);   // 1
  • 上記の例のwindow.わあ、これ.aの値はいずれも1に出力される.
  • の理由は、JavaScript内のすべての変数が特定のオブジェクト(LexicalEnvironment)のPropertyとして動作するためである.
  • ランタイムコンテキストは変数を収集し、それをLEのProperty♥として保存します.その後、変数が呼び出されると、L.Eがクエリされ、一致するPropertyがある場合は、その値が返されます.
  • 簡単(window.)省略と考えられる
  • var変数ではなくウィンドウ構成を指定します.
    var a = 1;
    window.b = 2;
    console.log(a, window.a, this.a); // 1 1 1
    console.log(b, window.b, this.b); // 2 2 2
    グローバル変数宣言とグローバルオブジェクトの初期割当ては同じ結果を生成します.
    ただし、グローバル変数宣言とグローバルオブジェクトの初期割り当ての間に差が生じることがあります.これが、シャットダウンするかどうか、および構成可能かどうか(変更および削除可能)です.
    次はグローバル変数、グローバルオブジェクトの削除操作です.
    var a = 1;    
    delete window.a;    // false
    console.log(a, window.a, this.a);   /// 1 1 1
    
    window.c = 3;
    delete window.c; // true
    console.log(c, window.c, this.c);  // Uncaught ReferenceError: c is not defined
    上記の例では、異なる点を示しています.変数にdelete演算子(window.)を使用する省略したと理解できる.
  • (window.) グローバルオブジェクトのプロパティとして指定すると削除されます.
  • (var)ですが、グローバル変数として宣言されている場合は削除されません.これは,ユーザの予期せぬ削除を防止するための防御戦略である.(false return)
  • メソッドを呼び出すと、メソッド内部のthis
  • 関数:事前定義動作を実行するコードのセットであり、独立機能
  • を実行する.
  • メソッド:事前定義動作を実行するコードのセットであり、自分のターゲットオブジェクトを呼び出すことに関連する動作
  • を実行する.
    var func = function(x) {
    	console.log(this, x);
    };
    func(1);   // Window {...} 1
    
    var obj = {
    	method: func
    }
    obj.method(2);  // { method: f } 2
  • funcという匿名関数を呼び出し、グローバルオブジェクトウィンドウ
  • を出力します.
  • obj.methodというメソッドが呼び出され、objが出力されます.
  • 、すなわち、元の匿名関数はそのままであり、変数に含めて呼び出すか、objオブジェクトに割り当てられたpropertyで呼び出すと発生する.
  • メソッド内部のthis
    メソッドで関数を呼び出すと、呼び出し主体が関数名(property名)の前のオブジェクトになります.
    var obj = {
    	methodA: function () { console.log(this); },
    	inner: {
    		methodB: function () { console.log(this); }
    	}
    };
    
    object.methodA();   // {methodA: f, inner: {...} } ( === obj )
    object.inner.methodB();  // {methodB: F} ( === obj.inner)
    関数として呼び出されたときの関数内部のthis
    1)関数内部のthis
  • 関数を関数として呼び出す場合は、この値は指定されません.これは,開発者がコードに直接関与するため呼び出し主体(オブジェクト)を指定しないため,呼び出し主体の情報
  • を知ることができないためである.
    したがって、関数のthisはグローバルオブジェクトを指します.2)メソッド内部関数のthis
    var obj1 = {
    	outer: function() {
    		console.log(this);   // (1) obj1
    		var innerFunc = function() {
    			console.log(this);    // (2) 전역객체(window) (3)obj2
    		}
    		innerFunc(); // --- (2) 실행
    
    		var obj2 = {
    			innerMethod : innerFunc
    		};
    		object2.innerMethod(); // --- (3) 실행
    	}
    }
    obj1.outer(); // ----(1) 실행
  • このバインディングについては、関数の実行時の環境(メソッドの内部または関数の内部など)は重要ではありません.重要なのは、関数を呼び出す構文の前に点または角カッコタグがあるかどうかです.
    このアイテムをバインドしない関数
  • ES 6は、関数内部のこのグローバルオブジェクトピボット問題を補うための新しい矢印関数(矢印関数)を導入した.
  • 実行コンテキストが生成されると、
  • 矢印関数でバインド処理が失われるため、親ミラーのこの処理を使用できます.
  • var obj = {
    	outer: function() {
    		console.log(this);    // (1) { outer: f}
    		var innerFunc = () => {
    			console.log(this);
    		};
    		innerFunc();
    	}
    }
    obj.outer();
    コールバック関数を呼び出すと、関数内部のthis
  • コールバック関数とは、関数Aの制御権を他の関数(または方法)Bに渡す場合、関数Aをコールバック関数と呼ぶ.
  • コールバック関数では、これは状況に応じて変化する.
  • の制御を持つ関数(メソッド)は、コールバック関数が何として機能するかを決定し、特に定義されていない場合はグローバルオブジェクトを表示します.
  • コンストラクション関数のthis
  • ジェネレータ関数:いくつかの共通の性質を持つオブジェクトを作成するための関数
  • オブジェクト向け言語:ジェネレータは、クラスを介して作成されたオブジェクトをインスタンスと呼びます.
  • プログラミング「ジェネレータ」は、特定のインスタンスを作成するためのフレームワーク
  • である.
  • jsでnewコマンドを使用して関数を呼び出すと、この関数はコンストラクション関数として実行されます.
  • 関数がコンストラクション関数として呼び出される場合、内部の特定のインスタンス自体が新しく作成されたインスタンスである.
    例)
    var Cat = function(name, age) { //  Cat 변수에 익명 함수 할당
    	this.bark = "야옹";
    	this.name = name;
    	this.age = age;
    }
    
    var choco = new Cat('초코', 7);  // 생성자 함수 내부에서의 this는 choco 인스턴스
    console.log(choco);
    
    // Cat { bark: "야옹", name: "초코", age: 7} --- Cat 클래스의 인스턴스 객체 출력
    2.このアイテムを明示的にバインドする方法
    他のオブジェクトは、以下の方法でバインドすることもできます.(call,apply,bindメソッド)1)callメソッド
    Function.prototype.call(thisArg[, arg1[, arg2[, ...]]])
  • 呼び出し方法:コマンド
  • は、メソッド呼び出し主体としての関数を直ちに実行する
  • 呼び出し方法の最初のパラメータをこのパラメータにバインドし、後続のパラメータを呼び出す関数のパラメータとして
  • を使用する.
  • すなわち、関数を直接実行するとグローバルオブジェクトが参照されますが、callメソッドを使用して任意のオブジェクトを
  • に指定できます.
    var func = function (a, b, c) {
    	console.log(this, a, b, c);
    }
    
    func(1, 2, 3); // Window{ ... } 1 2 3
    func.call({ x: 1}, 4, 5, 6); // { x:1 } 4 5 6
    2)応用方法
    Function.prototype.apply(thisArg[, argsArray])
  • applyメソッド:callメソッドと機能的に同じです.ただし、配列内の要素呼び出し関数として2番目のパラメータを指定するパラメータ
  • var func = function (a, b, c) {
    	console.log(this, a, b, c);
    }
    
    func(1, 2, 3); // Window{ ... } 1 2 3
    func.apply({ x: 1}, [4, 5, 6]); // { x:1 } 4 5 6
    call/applyメソッドを使用して、重複を減らすことができます.次の例は、コンストラクション関数の内部に他のコンストラクション関数と共通の内容がある場合、callまたはapplyを使用して他のコンストラクション関数を呼び出して重複を減らす例です.
    function Person(name, gender) {
      this.name = name;
      this.gender = gender;
    }
    
    function Student(name, gender, school) {
      Person.call(this, name, gender);
      this.school = school;
    }
    
    function Employee(name, gender, company) {
      Person.call(this, name, gender);
      this.company = company;
    }
    
    var by = new Student("보영", "female", "단국대");
    var jn = new Employee("재난", "male", "구글");
    3)bindメソッド
    関数バインドは、特定のthis値と特定のパラメータを渡すことで別の関数を呼び出す関数です.多くのJavaScriptライブラリでは、関数を特定のコンテキストにバインドする関数が作成されています.通常、これらの関数はbind()と呼ばれます.基本構成は次のとおりです.(出典:https://blog.sonim1.com/158)
    function bind(fn, context){
        return function(){
            return fn.apply(context, arguments);
        }
    }
    ECMAScript 5はbind()メソッドを導入し、以下に示す.
    Function.prototype.bind(thisArg[, arg1[, arg2[, ...]]])
  • ES 5に追加された機能.callと同様ですが、すぐに呼び出されていないthisとパラメータに基づいて新しい関数が返されます.
  • 、すなわちbind法の2つの目的は、この方法を関数に予め適用し、一部の適用関数を実装することである.
    var func = function (a, b, c, d){
      console.log(this, a, b, c, d);
    }
    func(1, 2, 3, 4);   // Window{...} 1 2 3 4
    
    var bindFunc1 = func.bind({ x: 1 });
    bindFunc1(5, 6, 7, 8);  // { x: 1 } 5 6 7 8
    
    var bindFunc2 = func.bind({ x: 1 }, 4, 5);
    bindFunc2(6, 7);     // { x: 1} 4 5 6 7
    bindFunc2(8, 9);     // { x: 1} 4 5 8 9
    4)矢印関数の例外
  • ES 6で新しく導入された矢印関数は、実行コンテキストの作成時にバインディングを含まない.
  • 、つまり、この関数の内部にはthisはまったくありません.アクセスするにはscopeチェーンでthisに最も近いthisにアクセスすれば、
  • にアクセスできます.
    var obj = {
      outer: function() {
        console.log(this);  // { outer: [Function: outer] }
        var innerFunc = () => {
          console.log(this);  // { outer: [Function: outer] }
        }
        innerFunc();
      }
    }
    obj.outer();
    5)個別のパラメータが受信された場合(コールバック関数のthis)
    パラメータとして
  • コールバック関数を受信する方法によっては、パラメータとして指定する他のオブジェクト(thisArg)を指定できます.
  • の配列方法では、Each(ex.foreach、map、filter、some、each、find、findIndex、flatMap、from、およびES 6のSet、Map)
  • が一般的である.
    foreachメソッドの例:
    var report = {
      sum: 0,
      count: 0,
      add: function () {
    		// arguments 를 배열로 변환해서 args 변수에 담는다
        var args = Array.prototype.slice.call(arguments); 
    		// 해당 배열(args)를 순회하면서 콜백 함수 실행
        args.forEach(function (entry) {
          this.sum += entry;
          ++this.count;
        }, this); // 콜백 함수 내부에서의 this가 해당 this로 바인딩 됨! 
      },
      average: function () {
        return this.sum / this.count;
      },
    };
    report.add(60, 85, 95);
    console.log(report.sum, report.count, report.average()); // 240 3 80
    <解説>
  • 60,85,90をパラメータとしてaddメソッドを呼び出し、これら3つのパラメータを配列してforeachメソッド
  • を実行する
  • コールバック関数では、addメソッドで伝達されるため、thisはaddメソッドのthis(report)を表す.
  • に従って、配列された3つの要素の中で巡回報告を行う.sum値とレポート.count値は順次変更され,巡回終了後に報告される.sumは240、reportがあります.countは3の
  • を含む
    ソース
  • 鄭在男、『Core Javascript』、ウィキペディア(2019)、p 65-93.
  • 19.JavaScript-バインド関数