JavaScript this


this


JavaScriptでは、これが難関です.いつものように、勉強も忘れて、最後に一回覚えました.やはり勉強を繰り返すことが答えだと思います.

What?


ブラウザコンソールでthis==window



関数でもthis==window



ブラウザでは、これは基本的にwindowです.ではwindowではない場合もありますか?

オブジェクトのメソッド


オブジェクトメソッドでは、thisはオブジェクトを指します.これは、オブジェクトのメソッドを呼び出すと、内部でこのメソッドが変更されるためです.

下図のように結果が異なります.

呼び出すときは、呼び出す関数がオブジェクトの方法なのか関数なのかが重要です.obj 2はobjです.aなので、オブジェクトの方法ではありません.

bind, call, apply


bind,call,applyはこの点を明確に変える関数法である.bind、call、applyを使用すると、オブジェクトを指します.


生成者


作成者はこれを最初から書きます.newを直接割り当てないとwindowになります.

newを使用すると、thisはジェネレータによって生成されるインスタンスになります.

ビジネス(イベントリスナー、Jクエリー、レスポンス...)


次のようにbodyにイベントリスナーが加わると、windowではなくbodyになります.イベントが発生すると、これは内部で変更されます.内部が変わっているので、ある程度は受け入れます.(これはイベントを受信するHTML要素です)

ES 6 Arrow Functionを使用すると、親関数のthisが取得されます.(Now Window)

整理する


このデフォルトはwindowオブジェクトです.オブジェクトメソッド、bind、call、apply、newを使用して、ウィンドウを指すオブジェクトのバインド範囲をオブジェクトに変更できます.また、イベントリスナーまたは他のライブラリでは、このを内部で変更できます.この点を常に確認しなければならない.デフォルトはwindowを指します.

注)MDN


MDNでの説明を見てみましょう.
JavaScriptでは、このキーワードの動作は他の言語とは少し異なります
ほとんどの場合、thisの値は関数を呼び出す方法で決定されます.
実行時に割当てに設定できず、関数を呼び出すときに異なる場合があります.
ES 5は、関数の番号を考慮せずにbindメソッドを導入してこの値を設定する.
ES 6はArraw関数を追加し、このバインディングを自分で向上させることはありません.
const test = {
  prop: 42,
  func: function() {
    return this.prop;
  },
};

console.log(test.func());
// expected output: 42

Value


実行コンテキスト(global、window、eval)のPropertyは、常に非厳格モードでオブジェクトを参照します.厳密モードでは、任意の値で指定できます.

グローバルコンテキスト


グローバル実行コンテキストのthisは、厳密なモードを考慮せずにグローバルオブジェクトを参照します.
// 웹 브라우저에서는 window 객체가 전역 객체
console.log(this === window); // true

a = 37;
console.log(window.a); // 37

this.b = "MDN";
console.log(window.b)  // "MDN"
console.log(b)         // "MDN"

関数コンテキスト


関数内部では、thisの値は関数を呼び出す方法によって決定されます.

単純呼び出し


デフォルトでは、ブラウザはグローバルオブジェクトを参照します.これは厳格モード(非厳格モード)ではなく、呼び出しによって設定されていないためです.
function f1() {
  return this;
}

// 브라우저
f1() === window; // true

// Node.js
f1() === global; // true
逆に、厳格モードでは、thisは実行コンテキストに入り、設定された値を保持するため、次の例ではundefinedとして保持される
function f2(){
  "use strict"; // 엄격 모드 참고
  return this;
}

f2() === undefined; // true
この値を1つのコンテキストから別のコンテキストに渡すには、call()、apply()を使用します.
例1
// call 또는 apply의 첫 번째 인자로 객체가 전달될 수 있으며 this가 그 객체에 묶임
var obj = {a: 'Custom'};

// 변수를 선언하고 변수에 프로퍼티로 전역 window를 할당
var a = 'Global';

function whatsThis() {
  return this.a;  // 함수 호출 방식에 따라 값이 달라짐
}

whatsThis();          // this는 'Global'. 함수 내에서 설정되지 않았으므로 global/window 객체로 초기값을 설정한다.
whatsThis.call(obj);  // this는 'Custom'. 함수 내에서 obj로 설정한다.
whatsThis.apply(obj); // this는 'Custom'. 함수 내에서 obj로 설정한다.
例2
function add(c, d) {
  return this.a + this.b + c + d;
}

var o = {a: 1, b: 3};

// 첫 번째 인자는 'this'로 사용할 객체이고,
// 이어지는 인자들은 함수 호출에서 인수로 전달된다.
add.call(o, 5, 7); // 16

// 첫 번째 인자는 'this'로 사용할 객체이고,
// 두 번째 인자는 함수 호출에서 인수로 사용될 멤버들이 위치한 배열이다.
add.apply(o, [10, 20]); // 34
非厳格モードでthisに渡される値がオブジェクトでない場合、callとapplyはオブジェクトに変換しようとします.null値とundefined値はグローバルオブジェクトになります.元の値(7やfooなど)は、関連するコンストラクション関数を使用してオブジェクトに変換されるため、元の数値7はnew number(7)からオブジェクトに変換され、文字列「foo」はnew String(「foo」)からオブジェクトに変換されます.
function bar() {
  console.log(Object.prototype.toString.call(this));
}

bar.call(7);     // [object Number]
bar.call('foo'); // [object String]
bar.call(undefined); // [object global]

bind


ES 6はFunctionprototype.bindを導入した.呼び出しf.bind(object)は、fと同じ本文および範囲を生成するが、これは元の関数を有する新しい関数を生成する.新しい関数のthisは、呼び出し方法にかかわらずbind()の最初のパラメータとして永続的に固定されます.
function f() {
  return this.a;
}

var g = f.bind({a: 'azerty'});
console.log(g()); // azerty

var h = g.bind({a: 'yoo'}); // bind는 한 번만 동작함!
console.log(h()); // azerty

var o = {a: 37, f: f, g: g, h: h};
console.log(o.a, o.f(), o.g(), o.h()); // 37, 37, azerty, azerty

Arrow Function


矢印関数では、これは自分を囲む静的範囲です.グローバル・コードは、グローバル・オブジェクトを指します.
var globalObject = this;
var foo = (() => this);
console.log(foo() === globalObject); // true

var obj = {func: foo};
console.log(obj.func() === globalObject); // true

// call을 사용한 this 설정 시도
console.log(foo.call(obj) === globalObject); // true

// bind를 사용한 this 설정 시도
foo = foo.bind(obj);
console.log(foo() === globalObject); // true

/*화살표 함수를 call(), bind(), apply()를 사용해 호출할 때 this의 값을 정해주더라도 무시합니다. 사용할 매개변수를 정해주는 건 문제 없지만, 첫 번째 매개변수(thisArg)는 null을 지정해야 합니다.*/
どのような方法を使用してもfooのthisは生成点に設定されます.他の関数で作成した矢印関数にも適用されます.これはカプセル化されたLexicalコンテキストによって維持されます.
// this를 반환하는 메소드 bar를 갖는 obj를 생성합니다.
// 반환된 함수는 화살표 함수로 생성되었으므로,
// this는 감싸진 함수의 this로 영구적으로 묶입니다.
// bar의 값은 호출에서 설정될 수 있으며, 이는 반환된 함수의 값을 설정하는 것입니다.
var obj = {
  bar: function() {
    var x = (() => this);
    return x;
  }
};

// obj의 메소드로써 bar를 호출하고, this를 obj로 설정
// 반환된 함수로의 참조를 fn에 할당
var fn = obj.bar();

// this 설정 없이 fn을 호출하면,
// 기본값으로 global 객체 또는 엄격 모드에서는 undefined
console.log(fn() === obj); // true

// 호출 없이 obj의 메소드를 참조한다면 주의하세요.
var fn2 = obj.bar;
// 화살표 함수의 this를 bar 메소드 내부에서 호출하면
// fn2의 this를 따르므로 window를 반환할것입니다.
console.log(fn2()() == window); // true
上記の例ではobj.barに割り当てられた関数(匿名関数Aと呼ぶ)は、矢印関数によって生成された他の関数(匿名関数Bと呼ぶ)を返す.その結果、関数Bが呼び出されると、Bのthisは永久にobjとなる.bar(関数A)のthisに設定します.返された関数(関数B)が呼び出されると、これは常に初期設定の値となります.上記のコード例では、関数Bのthisが関数Aのthis objとして設定されているため、objの設定は、通常、グローバルオブジェクトとして定義または設定されていない方法で呼び出される場合(または、前の例のようにグローバル実行コンテキストで他の方法を使用する場合)にも保持される.(?????????????????????)

オブジェクトとしてのアプローチ。


関数をオブジェクトとして呼び出す方法は、そのオブジェクトの値を使用します.
var o = {
  prop: 37,
  f: function() {
    return this.prop;
  }
};

console.log(o.f()); // 37

var o = {prop: 37};

function independent() {
  return this.prop;
}

o.f = independent;

console.log(o.f()); // logs 37
これは,oのメンバfから関数を呼び出すことだけが重要であることを示している.
このバインドは、メンバー・オブジェクトに最も直接影響します.以下の例で関数を実行すると、オブジェクトo.bのメソッドgとして呼び出される.実行すると、関数内部のthisはo.bを表します.オブジェクトは、自身がoのメンバーの1つであることを重視しない.最も直接的な参照が重要です.

オブジェクトのプロトタイプチェーンのthis


同じ概念でも,オブジェクトのプロトタイプチェーンのどこかで定義する方法は同じである.メソッドがオブジェクトのプロトタイプチェーンの上に存在する場合、thisの値はオブジェクトにメソッドの値を持つように設定されます.
var o = {
  f:function() { return this.a + this.b; }
};
var p = Object.create(o);
p.a = 1;
p.b = 4;

console.log(p.f()); // 5
この例では、f属性のない変数pで指定されたオブジェクトがプロトタイプから継承されます.しかし、これは最終的にoの中でf人のメンバーを見つける問題にはなりません.p.fの検索と参照を開始するため、関数のthisはpとして表されるオブジェクト値を取ります.すなわち、fはpのメソッドとして呼び出されてから、pを表す.JavaScriptプロトコルタイプ継承の興味深い機能です.

アクセス者と設定者のthis


もう一度同じ概念です.関数は、アクセス者と設定者から呼び出されても同じです.アクセス者または設定者の関数であるthisは、アクセスまたは設定属性を持つオブジェクトにバインドされます.
function sum() {
  return this.a + this.b + this.c;
}

var o = {
  a: 1,
  b: 2,
  c: 3,
  get average() {
    return (this.a + this.b + this.c) / 3;
  }
};

Object.defineProperty(o, 'sum', {
    get: sum, enumerable: true, configurable: true});

console.log(o.average, o.sum); // 2, 6

ジェネレータとして


newキーとともに使用されるコンストラクション関数として関数を使用すると、新しく作成されたオブジェクトにバインドされます.
function C() {
  this.a = 37;
}

var o = new C();
console.log(o.a); // 37


function C2() {
  this.a = 37;
  return {a: 38};
}

o = new C2();
console.log(o.a); // 38

DOMイベントプロセッサとして


イベントリスナーとして関数を使用する場合は、イベントを送信する要素に設定します.addEventListener以外の方法でプロセッサを追加しない限り、一部のブラウザではこの規則に従いません.
// 처리기로 호출하면 관련 객체를 파랗게 만듦
function bluify(e) {
  // 언제나 true
  console.log(this === e.currentTarget);
  // currentTarget과 target이 같은 객체면 true
  console.log(this === e.target);
  this.style.backgroundColor = '#A5D9F3';
}

// 문서 내 모든 요소의 목록
var elements = document.getElementsByTagName('*');

// 어떤 요소를 클릭하면 파랗게 변하도록
// bluify를 클릭 처리기로 등록
for (var i = 0; i < elements.length; i++) {
  elements[i].addEventListener('click', bluify, false);
}

インラインイベントハンドラ


インラインイベントハンドラとしてコードを使用する場合は、プロセッサのDOM要素を配置するように設定します.
<button onclick="alert(this.tagName.toLowerCase());">
  this 표시
</button>
上の警告ウィンドウにbuttonが表示されます.外部コードのみがこのように設定します.
<button onclick="alert((function() { return this; })());">
  내부 this 표시
</button>

ソース


MDN this
JavaScriptのthisは何ですか?