JavaScript 함수의 this 파헤치기

JavaScript 함수에서 this는 현재 실행되는 함수가 고정된 객체를 가리킨다. 단, Arrow function에서는 구문상의 this(Arrow function이 정의된 스코프의 this)를 가리킨다.

아래 Node.js 코드를 살펴보자.

global.price = Number.MAX_SAFE_INTEGER;

function getPrice() {
  return this.price;
}

const car = {
  price: 200,
  getPrice: function() {
    return this.price;
  }
};

const air = {
  price: 300,
  getPrice: () => this.price
};

function House() {
  this.price = 400;
  this.getPrice = () => this.price;
}

console.log(getPrice());       // 9007199254740991
console.log(car.getPrice());   // 200
console.log(air.getPrice());   // undefined
const house = new House()
console.log(house.getPrice()); // 400
  • 전역으로 정의된 함수 getPrice()thisglobal1이다.
  • 객체 car에 정의된 getPrice()는 객체 car에 고정되어있다. 이때 this는 객체 car이다.
  • 객체 air에 정의된 getPrice()는 Arrow function이며, lexical this가 없어 this는 빈 객체({})이다.
  • 생성자 House()에서 정의된 getPrice()는 Arrow function이며, 이때 this는 스코프의 this인 House 인스턴스이다.

this 바인딩

함수에 this를 고정하는 것을 this를 바인딩한다고 말한다.

global.price = Number.MAX_SAFE_INTEGER;

function getPrice() {
  return this.price;
}

const bag = { price: 100 };
const car = { price: 200 };
const getCarPrice = getPrice.bind(car);

console.log(getPrice());          // 9007199254740991
console.log(getPrice.apply(bag)); // 100
console.log(getCarPrice()));      // 200
console.log(getPrice.call(car));  // 200

Function.prototype.apply(thisArg, [argsArray])

this와 arguments를 고정하고 호출한다.
foo.bind(thisArg, [argsArray])()foo.apply(thisArg, [argsArray])와 같다.


Function.prototype.bind(thisArgs, [argsArray])

this와 argument를 고정시킨 새로운 함수를 반환한다.


Function.prototype.call(thisArg, arg1, arg2, …)

apply와 동일하지만 argument를 배열이 아닌 argument list로 받는 것이 차이.
foo.apply(thisArg, argsArray)foo.call(thisArg, ...argsArray)와 같다.


apply와 call은 객체와 인자를 바인딩하여 만들어진 함수를 호출하는 것이지만, bind는 새로운 함수를 반환한다.

클래스와 this

ES6에서 도입된 클래스 문법으로는 다음과 같이 작성할 수 있다.

class Product {
  constructor(price) {
    this.price = price;
  }

  getPrice() {
    return this.price;
  }
}


class Bag extends Product {
  constructor() {
    super(100);
  }
}

class Car extends Product {
  constructor() {
    super(200);
  }
}

const bag = new Bag();
const car = new Car();
console.log(bag.getPrice()); //100
car.price = 10000;
console.log(car.getPrice()); //10000

이때 getPrice()this는 해당 인스턴스이다.


  1. "use strict"로 strict mode를 사용한다면 this의 값은 undefined이다.