JavaScript this

5853 ワード

this


動作を表す方法は、その属するオブジェクトの状態、すなわちPropertyを参照して変更できる必要があります.メソッドが属するオブジェクトのプロパティを参照する場合は、まずそのオブジェクトを指す識別子を参照する必要があります.
const circle = {
  // 프로퍼티: 객체 고유의 상태 데이터
  radius: 5,
  // 메서드: 상태 데이터를 참조하고 조작하는 동작
  getDiameter() {
    // 이 메서드가 자신이 속한 객체의 프로퍼티나 다른 메서드를 참조하려면
    // 자신이 속한 객체인 circle을 참조할 수 있어야 한다.
    return 2 * circle.radius;
  }
};

console.log(circle.getDiameter()); // 10
これは、自己参照変数(self-reference variable)です.これは、所属するオブジェクトまたは作成するインスタンスを指します.これにより、オブジェクトまたは作成するインスタンスに属するプロシージャまたはメソッドを参照できます.
thisが指す値(すなわちthisバインド)は、関数呼び出しによって動的に決定されます.
// 생성자 함수
function Circle(radius) {
  // this는 생성자 함수가 생성할 인스턴스를 가리킨다.
  this.radius = radius;
}

Circle.prototype.getDiameter = function () {
  // this는 생성자 함수가 생성할 인스턴스를 가리킨다.
  return 2 * this.radius;
};

// 인스턴스 생성
const circle = new Circle(5);
console.log(circle.getDiameter()); // 10
コンストラクション関数の内部にあるthisは、コンストラクション関数が作成するインスタンスを指します.このように、thisは状況によって指す対象が異なります.
JavaやC++などのクラスベースの言語では、thisは常にクラス生成のインスタンスを指します.ただし、javascriptのthisは、関数呼び出しに基づいて、thisにバインドされる値、すなわちthisバインドを動的に決定します.また、strict modeもこのバインドに影響します.
// this는 어디서든지 참조 가능하다.
// 전역에서 this는 전역 객체 window를 가리킨다.
console.log(this); // window

function square(number) {
  // 일반 함수 내부에서 this는 전역 객체 window를 가리킨다.
  console.log(this); // window
  return number * number;
}
square(2);

const person = {
  name: 'Lee',
  getName() {
    // 메서드 내부에서 this는 메서드를 호출한 객체를 가리킨다.
    console.log(this); // {name: "Lee", getName: ƒ}
    return this.name;
  }
};
console.log(person.getName()); // Lee

function Person(name) {
  this.name = name;
  // 생성자 함수 내부에서 this는 생성자 함수가 생성할 인스턴스를 가리킨다.
  console.log(this); // Person {name: "Lee"}
}

const me = new Person('Lee');
ただし、これはオブジェクトを参照するpropertyまたはメソッドの自己参照変数であるため、通常はオブジェクトのメソッド内部またはコンストラクション関数の親にのみ意味があります.

関数呼び出しとバインド


このバインド(この値にバインドされる)は、関数が呼び出される方法(すなわち、関数がどのように呼び出されるか)によって動的に決定されます.
関数を呼び出す方法は多種多様である.
1.一般関数の呼び出し
2.呼び出し方法
3.コンストラクタの呼び出し
4. Function.prototype.apply/call/bindメソッドによる間接呼び出し
// this 바인딩은 함수 호출 방식에 따라 동적으로 결정된다.
const foo = function () {
  console.dir(this);
};

// 동일한 함수도 다양한 방식으로 호출할 수 있다.

// 1. 일반 함수 호출
// foo 함수를 일반적인 방식으로 호출
// foo 함수 내부의 this는 전역 객체 window를 가리킨다.
foo(); // window

// 2. 메서드 호출
// foo 함수를 프로퍼티 값으로 할당하여 호출
// foo 함수 내부의 this는 메서드를 호출한 객체 obj를 가리킨다.
const obj = { foo };
obj.foo(); // obj

// 3. 생성자 함수 호출
// foo 함수를 new 연산자와 함께 생성자 함수로 호출
// foo 함수 내부의 this는 생성자 함수가 생성한 인스턴스를 가리킨다.
new foo(); // foo {}

// 4. Function.prototype.apply/call/bind 메서드에 의한 간접 호출
// foo 함수 내부의 this는 인수에 의해 결정된다.
const bar = { name: 'bar' };

foo.call(bar);   // bar
foo.apply(bar);  // bar
foo.bind(bar)(); // bar

一般関数の呼び出し


デフォルトでは、thisはグローバルオブジェクトをバインドします.
function foo() {
  console.log("foo's this: ", this);  // window
  function bar() {
    console.log("bar's this: ", this); // window
  }
  bar();
}
foo();
ネストされた関数を通常の関数として呼び出すと、関数内部のthisはグローバルオブジェクトをバインドします.
function foo() {
  'use strict';

  console.log("foo's this: ", this);  // undefined
  function bar() {
    console.log("bar's this: ", this); // undefined
  }
  bar();
}
foo();
strict modeが適用された一般的な関数の内部で、thisは未定義のものをバインドします.
function foo() {
  'use strict';

  console.log("foo's this: ", this);  // undefined
  function bar() {
    console.log("bar's this: ", this); // undefined
  }
  bar();
}
foo();
コールバック関数が通常の関数として呼び出されると、コールバック関数内部のthisもグローバルオブジェクトをバインドします.
var value = 1;

const obj = {
  value: 100,
  foo() {
    console.log("foo's this: ", this); // {value: 100, foo: ƒ}
    // 콜백 함수 내부의 this에는 전역 객체가 바인딩된다.
    setTimeout(function () {
      console.log("callback's this: ", this); // window
      console.log("callback's this.value: ", this.value); // 1
    }, 100);
  }
};

obj.foo(); 
このように、ネスト関数とコールバック関数を含む通常の関数で呼び出されるすべての関数の内部にあるthisは、グローバルオブジェクトをバインドします.
const anotherPerson = {
  name: 'Kim'
};
// getName 메서드를 anotherPerson 객체의 메서드로 할당
anotherPerson.getName = person.getName;

// getName 메서드를 호출한 객체는 anotherPerson이다.
console.log(anotherPerson.getName()); // Kim

// getName 메서드를 변수에 할당
const getName = person.getName;

// getName 메서드를 일반 함수로 호출
console.log(getName()); // ''
// 일반 함수로 호출된 getName 함수 내부의 this.name은 브라우저 환경에서 window.name과 같다.
// 브라우저 환경에서 window.name은 브라우저 창의 이름을 나타내는 빌트인 프로퍼티이며 기본값은 ''이다.
// Node.js 환경에서 this.name은 undefined다.

コンストラクタの呼び出し


コンストラクション関数の内部で、thisはコンストラクション関数が作成するインスタンスをバインドします.
// 생성자 함수
function Circle(radius) {
  // 생성자 함수 내부의 this는 생성자 함수가 생성할 인스턴스를 가리킨다.
  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
}

// 반지름이 5인 Circle 객체를 생성
const circle1 = new Circle(5);
// 반지름이 10인 Circle 객체를 생성
const circle2 = new Circle(10);

console.log(circle1.getDiameter()); // 10
console.log(circle2.getDiameter()); // 20

Function.prototype.apply/call/bindメソッドによる間接呼び出し

const person = {
  name: 'Lee',
  foo(callback) {
    // bind 메서드로 callback 함수 내부의 this 바인딩을 전달
    setTimeout(callback.bind(this), 100);
  }
};

person.foo(function () {
  console.log(`Hi! my name is ${this.name}.`); // Hi! my name is Lee.
});
これまで,関数呼び出し方式に基づいてthisバインドを動的に決定することを議論した.