본문 바로가기

이것저것 스터디📚/JavaScript

this

- this는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수이다.

- 자바나 C++ 같은 클래스 기반 언어에서 this는 언제나 클래스가 생성하는 인스턴스를 가리키지만, JavaScript의 this는 함수 호출 방식에 의해 동적으로 결정된다.

- 즉, 함수를 선언할 때 this가 바인딩할 객체가 정적으로 결정되는 것이 아닌, 함수를 호출할 때 함수가 어떻게 호출되었는지에 따라 this에 바인딩할 객체가 동적으로 결정된다.

 

* JavaScript에서의 함수 호출 방식에 따른 this

- 일반 함수 호출(전역 함수, 중첩 함수, 일반 함수로 호출되는 메서드 내에서 정의한 중첩 함수 내부, 콜백 함수) : 기본적으로 this에는 전역 객체가 바인딩 된다.

function foo() {
  console.log(this); // window
  function bar() {
    console.log(this); // window
  }
  bar();
}
foo();

- 메서드 호출 : 메서드 내부의 this는 메서드를 소유한 객체가 아닌 메서드를 호출한 객체가 바인딩 된다.

const person = {
  name: "Lee",
  getName() {
    return this.name;
  }
};

const anotherPerson = {
  name: "Kim"
};

anotherPeron.getName = person.getName;

console.log(anotherPerson.getName()); // Kim
// person의 name인 "Lee"가 아닌 "Kim"이 출력된다

- 생성자 함수 호출 : 생성자 함수 내부의 this에는 생성자 함수가 (미래에) 생성할 인스턴스가 바인딩된다.

function Circle(radius) {
  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
}

const circle = new Circle(5)
console.log(circle.getDiameter()); // 10

- 화살표 함수 호출 : 화살표 함수 내부에서의 this는 해당 화살표 함수가 선언된 컨텍스트(주로 상위 함수)의 this를 그대로 가리킨다. 또한 화살표 함수는 call, apply, bind 메서드를 사용하여 this를 변경할 수 없다.

window.id = 'Lee';
window.age = 30;

const user = {
  id: 'kim',
  age: '20',
  display1: function () {
    return `name:${this.id} age:${this.age}`;
  },
  display2: () => {
    return `name:${this.id} age:${this.age}`;
  },
  display3: function () {
    setTimeout(() => {
      console.log(`name:${this.id} age:${this.age}`);
    }, 3000);
  },
};
console.log(user.display1()); // name:"kim" age:20
console.log(user.display2()); // name:"Lee" age:30
console.log(user.display3()); // name:"kim" age:20
window.x = 1;
const normal = function () { return this.x; };
const arrow = () => this.x;

console.log(normal.call({ x: 10 })); // 10
// 화살표 함수는 call, apply, bind 메서드로 this를 바인딩할 수 없다
console.log(arrow.call({ x: 10 }));  // 1

* 정리

- this는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수이다. 자바나 C++ 과 같은 클래스 기반 언어와는 다르게 JavaScript에서는 함수를 선언할 때 this가 바인딩할 객체가 정적으로 결정되는 것이 아닌, 함수를 호출할 때 함수가 어떻게 호출되었는지에 따라 this에 바인딩할 객체가 동적으로 결정된다. 

 

- 일반 함수 호출(전역 함수, 중첩 함수, 일반 함수로 호출되는 메서드 내에서 정의한 중첩 함수 내부, 콜백 함수) : 기본적으로 this에는 전역 객체가 바인딩 된다.

- 메서드 호출 : 메서드 내부의 this는 메서드를 소유한 객체가 아닌 메서드를 호출한 객체가 바인딩 된다.

- 생성자 함수 호출 : 생성자 함수 내부의 this에는 생성자 함수가 (미래에) 생성할 인스턴스가 바인딩된다.

- 화살표 함수 호출 : 화살표 함수 내부에서의 this는 해당 화살표 함수가 선언된 컨텍스트(주로 상위 함수)의 this를 그대로 가리킨다. 또한 화살표 함수는 call, apply, bind 메서드를 사용하여 this를 변경할 수 없다.