16. this

함수의 호출 방식에 따라 this가 참조하는 값이 결정되는 this 바인딩

Index

this의 존재 당위성

함수 호출 방식과 this 바인딩



객체지향 프로그래밍에서 자신이 속한 객체의 프로퍼티를 참조하고 변경하는 것은 매우 중요합니다.
이는 객체의 상태(state)를 관리하고, 행동(behavior)과 데이터(data)를 결합하는 객제치향프로그래밍의 핵심 개념 중 하나이다.


1. this의 존재 당위성

🧐 Q. 객체 리터럴 방식으로 생성한 객체의 경우 메서드 내부에서 메서드 자신이 속한 객체를 가리키는 식별자를 재귀적으로 참조할 경우 어떠한 문제가 발생될까?

const circle = {
  radius: 5,
  getDiameter() {
    return 2 * circle.radius;
  },
};

// (1) 의도한 동작
console.log(circle.getDiameter()); // 10

// (2) 문제 상황
const anotehrCircle = circle;
anotherCircle.radius = 10;
console.log(anotherCircle.getDiameter()); // 20

// (3) 객체 참조 변경
const detachedMethod = circle.getDiameter;
console.log(detachedMethod()); // TypeError 또는 10 (의도치 않은 결과)

1.1 객체 이름에 의존

  • 메서드 내부에서 circle을 직접 참조하면, 해당 메서드는 항상 특정 이름(circle)에 묶여 동작합니다.
  • 객체를 복사하거나 다른 변수에 할당하면 참조가 깨지거나 의도치 않은 동작이 발생합니다.

1.2 재사용성 저하

  • 메서드를 다른 객체로 재사용하거나, 메서드만 별도로 호출하려는 경우 문제가 발생합니다.
  • this를 사용하지 않으면 메서드가 객체 독립적으로 동작하지 못합니다.


🧐 Q. 생성자 함수를 정의하는 시점에는 아직 인스턴스가 생성되기 이전이므로 인스턴스를 가르키는 식별자는 어떻게 알 수 있을까?

// (4) 인스턴스 생성의 전제, 생성자함수의 존재
function Circle(radius) {
  ????.radius = radius;
}

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

const circle = new Circle(5);

1.3 자기 참조 변수 필요

  • 생성자 함수가 생성할 인스턴스를 가리키는 식별자를 알 수 없기 때문에 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 특수한 식별자가 필요하다. 이를 위해 자바스크립트는 this라는 특수한 식별자를 제공한다.



2. 함수 호출 방식과 this 바인딩

// (1) 전역에서 this는 전역객체 window를 가리킨다.

console.log(this); // window

-----------------------------------------------------------------------------------------
// (2) 일반 함수 내부에서 this는 전역객체 window를 가리킨다.

  function square(number) {
  console.log(this); // window
 return number * number;
}
square(2);

-----------------------------------------------------------------------------------------
// (3) 메서드 내부에서 this는 메서드를 호출한 객체를 가리킨다.

const person = {
  name: 'Lee',
  getName() {
    console.log(this); // {name: "Lee", getNameL f}
    return this.name;
  }
};
console.log(person.getName());

-----------------------------------------------------------------------------------------
// (4) 생성자 함수 내부에서 this는 생성자 함수가 생성할 인스턴스를 가리킨다.

function Person(name) {
  this.name = name;
  console.log(this); // Person {name: 'Lee'}
}

const me = new Person('Lee');

-----------------------------------------------------------------------------------------
// (5) Function.prototype.apply/call/bind 메서드에 의한 호출

function getThisBinding() {
  return this;
}

const thisArg = { a: 1};

console.log(getThisBinding()); // window
// getThisBinding 함수를 호출하면서 인수로 전달할 객체를 getThisBinding 함수의 this에 바인딩한다.
console.log(getThisBinding.apply(thisArg)); // {a: 1}
console.log(getThisBinding.call(thisArg); // {a: 1}

// Function.prototype.bind 메서드는 apply와 call메서드와 달리 함수를 호출하지 않는다. 다만 첫 번째 인수로 전달한 값으로 this 바인딩이 교체된 함수를 새롭게 생성해 반환한다.
console.log(getThisBinding.bind(thisArg)); // getThisBinding
console.log(getThisBinding.bind(thisArg)()); // {a: 1}

Photo of this binding

Property of this binding

Ungmo Lee. (2020). Modern Javascript DeepDive. wikibooks. p.358.




reference: 모던자바스크립트 Deep Dive 22장. this