Post Detail Page

tech

Javascript에서 this 바인딩 이해하기

함수 호출 방식에 따라 결정되는 this

자바스크립트의 this는 함수가 어떻게 호출되었는가에 따라 가리키는 값이 달라집니다.

javascript-this-image

📌 일반 함수 호출

const cafe = {
  brand: '이디야',
  menu: '아메리카노',
  print: function () {
    console.log(this);
  },
};

const myCafe = cafe.print;
myCafe(); // 일반 함수 호출
  • myCafe 변수에 cafe.print를 할당하고 호출했기 때문에 myCafe()전역 컨텍스트에서 실행됩니다. 이때 this전역 객체window를 가리킵니다.

📌 메서드 호출(객체 프로퍼티 함수)

함수가 어떤 객체의 메서드로서 호출되는지에 따라 this가 달라집니다.

const cafe = {
  brand: '이디야',
  menu: '아메리카노',
  print: function () {
    console.log(this);
  },
};

cafe.print();
{brand: '이디야', menu: '아메리카노', print: ƒ}
  • this는 자신이 포함된 객체인 cafe를 가리키고, console.log(this)는 cafe 객체를 출력하게 됩니다.

const cafe = {
  brand: '이디야',
  menu: '아메리카노',

  newCafe: {
    brand: '이디야',
    menu: '라떼',
    print: function () {
      console.log(this);
    },
  },
};

cafe.newCafe.print();
{brand: '이디야', menu: '라떼', print: ƒ}
  • this는 호출된 메서드의 주체인 newCafe 객체 자체를 가리키고, console.log(this)는 newCafe 객체를 출력하게 됩니다.

📌 생성자 함수 호출

function Cafe(menu) {
  console.log(this);
  this.menu = menu;
}

let myCafe = new Cafe('latte');
console.log(myCafe);
Cafe {menu: 'latte'}
  • new 키워드를 사용하면, 자바스크립트는 새로운 객체를 생성하고 그 객체를 this로 바인딩합니다.

🔎 new 키워드를 삭제하고, Cafe 함수를 일반 함수로 사용한다면?

function Cafe(menu) {
  console.log(this);
  this.menu = menu;
}

let myCafe = Cafe('latte'); // 일반 함수로 사용됨
console.log(myCafe);
  • new 키워드를 생략하면 일반 함수로 호출되며, this는 전역 객체 window를 가리킵니다.
console.log(window.menu);  // 'latte'

📌 콜백 함수

const cafe = {
  brand: '이디야',
  menu: '',
  setMenu: function (menu) {
    this.menu = menu;
  },
};

function getMenu(menu, callback) {
  callback(menu);
}

getMenu('핫초코', cafe.setMenu);

console.log(cafe);
  • getMenu 함수에서 cafe.setMenu콜백으로 전달하면, setMenu는 메서드로서 호출되지 않고, 일반 함수로 호출됩니다.
console.log(window.menu)  // 핫초코

🔎 메서드로 직접 호출하기

const cafe = {
  brand: '이디야',
  menu: '',
  setMenu: function (menu) {
    this.menu = menu;
  },
};

function getMenu(menu) {
  cafe.setMenu(menu); // 메서드 호출
}

getMenu('핫초코');

console.log(cafe);
{brand: '이디야', menu: '핫초코', setMenu: ƒ}
  • cafe.setMenu 메서드로 호출되므로 thiscafe 객체를 가리키게 됩니다. 이때 this.menu는 cafe 객체의 menu에 '핫초코'를 할당하게 됩니다.

📌 화살표 함수

💡 화살표 함수의 this
화살표 함수의 this는 호출 방식과 상관없이 함수가 선언된 위치의 상위 스코프를 참조합니다.
이는 일반 함수가 호출될 때마다 this가 동적으로 바인딩되는 것과 달리, 화살표 함수는 선언 시점의 this가 고정됩니다.

🚨 일반 함수(콜백 호출)에서의 this 문제

function Counter() {
  this.count = 0;
  setInterval(function () {
    this.count++;
    console.log(this.count);
  }, 2000);
}

const counter = new Counter();
  • setInterval콜백 함수일반 함수로서 실행됩니다. 일반 함수의 경우 this는 함수가 호출된 방식에 따라 결정되며, 이때 콜백 함수는 전역 컨텍스트에서 실행되기 때문에, this는 전역 객체인 window를 가리키게 됩니다.
  • this.count++를 하려고 하면, this는 Counter 객체가 아닌 window를 가리키기 때문에 NaN이 2초마다 찍히게 됩니다.

화살표 함수에서의 this 바인딩

function Counter() {
  this.count = 0;
  setInterval(() => {
    this.count++;
    console.log(this.count);
  }, 2000);
}

const counter = new Counter();
  • 화살표 함수자신이 선언된 위치의 상위 스코프를 참조합니다. 화살표 함수가 Counter 객체의 컨텍스트에서 선언되었기 때문에, thisCounter 객체를 가리킵니다.

화살표 함수와 메서드 호출

const cafe = {
  brand: '이디야',
  menu: '아메리카노',
  print: () => {
    console.log(this);
  },
};

cafe.print();
  • print 메서드는 cafe 객체의 속성으로 정의되었지만, 화살표 함수는 cafe 객체의 상위 스코프, 즉 전역 객체 window를 참조하게 됩니다.
  • 객체의 메서드로서 this를 올바르게 바인딩하기 위해서는 일반 함수를 사용하는 것이 좋습니다.