このキーワードを深く説明する

4310 ワード

pythonなどの他のプログラミング言語に比べて、JavaScriptでのthisキーワードの表現は異なり、厳格なモードかどうかもthisのバインドに影響します.この中にはいろいろな方法があり、うっかりすると間違いになる可能性があります.そして、thisはダイナミックな役割ドメインのいとことして、JavaScriptの文法の役割ドメインとは大きく異なるので、JavaScriptの大きな穴と呼ばれています.(私もそう思います、2333)
ほとんどの場合、関数の呼び出し方法はthisの値を決定します.thisは実行中に値を割り当てることができず、関数が呼び出されるたびにthisの値が異なる場合があります.ここでは主に,ES 6における矢印関数におけるいくつかの一般的な呼び出し方式とthisについて議論する.
いくつかの一般的な呼び出し方法:
1.グローバル範囲でthisを使用すると、グローバルオブジェクトであるwindowを指します.
var a = 1;
console.log(this.a);  // 1

console.log(this === window); // true

this.b = "hello,world";
console.log(window.b);  // "hello,world"
console.log(b);         // "hello,world"

2.関数で呼び出されると、グローバルオブジェクトも指します.nodeではglobalを指します.
var a = 1;
function fn(){
  var a = 2;
  console.log(a);
}
fn(); //1

//       :
//     :
fn() === window;

// Node :
fn() === global;

ES 5の厳密なモードでは、グローバル変数は存在しないことに注意してください.thisは、実行コンテキストに入ったときの値を保持します.この場合、thisはundefinedになります.
"use strict"
function fn(a){
    console.log(this);
}
fn(1);   //undefined

fn() === undefined; // true

3.メソッド呼び出しtext.foo(); この例ではthisはtextオブジェクトを指します.このような動作は、関数の定義方法や位置の影響を受けないことに注意してください.このバインドは、最も近いメンバー参照の影響のみを受けます.
var text = {
  num: 1,
  foo: function() {
    return this.num;
  }
};

console.log(text.foo()); // 1

fn = text.foo;
text.a = {b: fn, num: 2};
console.log(text.a.b()); // 2

4.コンストラクション関数として使用される関数のthisは、コンストラクション中の新しいオブジェクトにバインドされます.
function Person(age){
  this.age = age;
}

var jake = new Person(18);
jake.age; //18

5.callメソッドまたはapplyメソッドを使用すると、関数内のthisは、関数呼び出しの最初のパラメータとして明示的に設定されます.
//       call apply        , this          
var obj = {a: 1};

//       global     。
var a = 2;

function fn() {
  // this            
  return this.a;  
}

fn();          // 2
fn.call(obj);  // 1
fn.apply(obj); // 1

callとapply関数を使用する場合は、thisに渡される値がオブジェクトでない場合、JavaScriptは内部ToObject操作を使用してオブジェクトに変換しようとします.
6.objを呼び出す.bind()ではobjと同じ関数体と役割ドメインを持つ関数を作成できますが、この関数がどのように呼び出されてもbindの最初のパラメータに永続的にバインドされます.
var obj = {name: 'Jake'};
function sayName(){
    console.log(this.name)
};
var fn = sayName.bind(obj);  
//       fn      
//    sayName     ,          this   obj
fn() //   : 'Jake'

7.プロトタイプチェーンのthisは、呼び出されたオブジェクトを指しています.これは理解しやすいです.
var fn = {
  add : function(){ 
    return this.a + this.b; 
  }
};
var p = Object.create(fn);
p.a = 1;
p.b = 2;

console.log(p.add()); // 3

8.関数がイベント処理関数として使用される場合、thisはイベントをトリガーする要素を指します.
  //     ,          
    function bluify(e){
      //            
      console.log(this);
      //      
      e.stopPropagation();
      //         
      e.preventDefault();      
      this.style.backgroundColor = '#A5D9F3';
    }
    //              
    var elements = document.getElementsByTagName('*');

    //  bluify           ,       ,      
    for(var i=0 ; i

矢印関数
この複雑さのため、JavaScriptで最もエラーが発生する要因の一つとなっています.したがって、ES 6の矢印関数にはthisバインドがありません.役割ドメインチェーンを検索して値を決定する必要があります.グローバルコードでは、グローバルオブジェクトとして設定されます.
var obj = this;
var foo = (() => this);
console.log(foo() === obj); // true

矢印関数はthisをバインドしないため、call()/apply()/bind()メソッドは矢印関数にとって入力パラメータにすぎず、thisには影響しません.
//       

var a = {foo: foo};
console.log(a.foo() === obj); // true
//  call   this
console.log(foo.call(a) === obj); // true
//  call   this
foo = foo.bind(a);
console.log(foo() === obj); // true

thisが文法的な面であることを考慮すると,厳格なモードではthisに関連する規則は無視される.(厳密モードでの影響は無視できます)
var a = () => {'use strict'; return this};
var b = () => { return this};
console.log(1,a() === window);
console.log(2,a() === b());
//1 true
//2 true

矢印関数をメソッドとして呼び出すと、thisはどうなりますか?
var obj = {
  a: 1,
  b: () => console.log(this.a, this),
  c: function() {
    console.log( this.a, this)
  }
}
obj.b();  // undefined Window{postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window,…}
obj.c();  // 1 {a: 1, b: ƒ, c: ƒ}

メソッドとしての矢印関数thisはグローバルオブジェクト(window)を指し、通常の関数のthisは呼び出したオブジェクトを指します.