JAN's History

자바스크립트에서 this 키워드 이해하기 본문

Javascript

자바스크립트에서 this 키워드 이해하기

JANNNNNN 2024. 10. 29. 17:02

이번에는 this 키워드에 대해 알아볼 거예요! this는 자바스크립트에서 조금 헷갈릴 수 있는 개념 중 하나죠. 어떻게 this가 결정되는지, 그리고 원하는 대로 this를 바꾸는 방법까지 자세히 살펴보도록 해요. 🙌

🎯 1. this 키워드란?

자바스크립트는 렉시컬 스코프(Lexical Scope)를 사용하기 때문에 일반적으로 상위 스코프는 정의 시점에 평가가 돼요. 하지만! this 키워드는 그렇지 않아요. 객체가 생성되는 시점에 this가 결정됩니다. 이 말은 객체나 함수가 언제 어떻게 호출되느냐에 따라 this가 가리키는 대상이 달라진다는 뜻이에요.

📝 예제 코드: this의 기본 동작

  • 아래 코드에서 this는 pome 객체를 가리키고 있어요. 이처럼 메서드 내에서 this는 해당 메서드를 호출한 객체를 참조합니다.
const pome = {
  type: '포메라니안',
  size: 'small',
  sayHello: function () {
    return `안녕하세요 저는 ${this.type}입니다.`; // 여기서 this는 pome 객체를 가리킵니다.
  },
};

console.log(pome.sayHello()); // "안녕하세요 저는 포메라니안입니다."

🎯 2. 생성자 함수와 this

생성자 함수에서의 this는 그 생성자 함수로부터 만들어지는 새로운 객체를 가리켜요.

📝 예제 코드: 생성자 함수와 this

  • 여기서는 new 키워드로 생성된 pome2 객체에 this가 매핑됩니다. 이 덕분에 sayHello() 메서드 안에서 this.type은 pome2의 type 속성을 참조하게 되는 것이죠.
function Dog(type, size) {
  this.type = type;
  this.size = size;

  this.sayHello = function () {
    return `안녕하세요 저는 ${this.type}입니다.`; // 여기서 this는 생성된 객체(pome2)를 가리킵니다.
  };
}

const pome2 = new Dog('포메라니안', 'small');
console.log(pome2.sayHello()); // "안녕하세요 저는 포메라니안입니다."

🎯 3. 프로토타입과 this

메서드를 프로토타입에 추가할 때에도 this가 올바른 객체를 참조해요. 하지만 내부에 별도의 함수를 정의할 경우, this가 다른 대상을 가리킬 수 있으니 주의해야 해요!

📝 예제 코드: 프로토타입과 this

Dog.prototype.dance = function () {
  function dance2() {
    return `${this.type}이 춤을 춥니다.`; // 여기서 this는 글로벌 객체를 가리킵니다.
  }
  return dance2();
};

console.log(pome2.dance()); // "undefined이 춤을 춥니다."

중요: 함수 안에 함수를 정의할 경우, 내부 함수의 this는 글로벌 객체(window 또는 global)를 가리키게 됩니다. 원하는 객체를 참조하려면 내부 함수에서 this를 사용할 때 주의가 필요해요!

🎯 4. this를 원하는 대로 매핑하기

this를 원하는 객체로 바꾸는 방법이 몇 가지 있어요:

  1. call(): 함수를 호출하면서 this로 사용할 객체를 지정할 수 있어요.
  2. apply(): call()과 비슷하지만, 인수를 배열 형태로 전달해요.
  3. bind(): 새로운 함수를 반환하면서 this로 사용할 객체를 지정해요.

📝 예제 코드: this 바인딩 

function returnType() {
  return this.type;
}

const pome3 = {
  type: '포메라니안',
};

console.log(returnType.call(pome3)); // "포메라니안"
console.log(returnType.apply(pome3)); // "포메라니안"

/**
 * 1) call -> 컴마를 기반으로 argument를 순서대로 넘겨줘야한다.
 * 2) apply -> argument를 리스트로 입력해야한다.
 */
function multiply(x, y, z) {
  return `${this.type} / 결과값 : ${x * y * z}`;
}

console.log(multiply.call(pome3, 3, 4, 5))
console.log(multiply.apply(pome3, [3, 4, 5]))

call과 apply를 사용하면 함수 호출 시 this를 원하는 객체로 매핑할 수 있어요.

중요: call()과 apply()의 차이

  1. call()은 인수를 콤마로 구분해 전달합니다.
  2. apply()는 인수를 배열로 전달해야 합니다.

bind()는 즉시 함수를 실행하지 않고, this가 지정된 새로운 함수를 반환해요.

📝 예제 코드: bind() 사용하기

const laterFunc = multiply.bind(pome3, 3, 4, 5);
console.log(laterFunc); // 바인딩된 함수가 반환됩니다.
console.log(laterFunc()); // "포메라니안 / 결과값 : 60"

중요: bind()를 사용할 때 주의할 점 bind()는 즉시 실행되는 게 아니라 나중에 실행할 수 있는 함수를 반환해요. 따라서 필요할 때만 실행되도록 할 수 있어요!

📌 정리

  • this가 가리키는 대상을 결정하는 규칙:
    1. 일반 함수 호출: this는 최상위 객체(global 또는 window)를 가리킵니다.
    2. 메서드로 호출: this는 호출한 객체를 가리킵니다.
    3. new 키워드 사용: 생성된 객체를 가리킵니다.
  • this를 원하는 객체로 매핑하려면 call(), apply(), 또는 bind()를 사용하세요.

🛠 실무적인 팁

this가 가리키는 대상을 잘 파악하고 사용하면 코드의 유연성과 재사용성을 높일 수 있어요. 특히 메서드 안에 함수를 정의할 때는 this가 글로벌 객체를 참조하지 않도록 조심해야 해요. call(), apply(), bind()를 적절히 사용해 원하는 대로 this를 컨트롤할 수 있습니다. 😊