JS 이모저모 - this

박기범·2021년 12월 22일
0

JavaScript 이모저모

목록 보기
2/3

본 시리즈는 JS를 공부하며 알게된 JS만의 특성이나 프로그래밍 기본기로써 중요한 내용들을 묶어 정리하는 시리즈입니다.
정해져있는 순서는 없으며, 각 항목들이 큰 연관을 갖고있지는 않습니다.
추후에 체계적으로 정리하여 글을 수정할 계획은 있습니다.

이번에는 짤막글이 되겠다.

간단명료하게 JS의 특이한 this에 대해서 짚어보도록 하자.

this in object

다음의 코드를 보자.

let user = {
  name: "John",
  age: 30,

  sayHi() {
    // 'this'는 '현재 객체'를 나타냅니다.
    alert(this.name);
  }

};

user.sayHi(); // John

위의 코드에서 this는 무엇을 가리킬까? 보통의 경우, 메소드 내부에서 this를 호출하면, 메소드 자신을 갖고있는 객체에 대해 접근한다. 즉, 객체 내부의 메소드는 this를 통해 객체 프로퍼티를 이용하게 된다. 위의 코드에서는 this가 sayHi()메소드를 갖고있는 user 객체를 가리킨다.

그런데 JS의 this 는 조금 특이한 점이 있다. 이제부터 알아보자.

자유로운 this

function sayHi() {
  alert(this);
}

sayHi();

JS에서는 this를 이렇게 모든 함수에 대해서 사용할 수 있다. 그렇다면, 위의 코드를 실행한 결과는 어떻게 되는가?

정답은 undefined가 출력된다.

객체 내부에서 호출되어 this가 가리킬 객체가 없다면, this는 undefined로 초기화된다.

그리고 또 하나의 독특한 점은, JS의 this가 가리키는 대상은 런타임에서 결정된다는 것이다.

다음의 코드를 보자.

let user = { name: "John" };
let admin = { name: "Admin" };

function sayHi() {
  alert( this.name );
}

// 별개의 객체에서 동일한 함수를 사용함
user.f = sayHi;
admin.f = sayHi;


user.f(); 
admin.f();

admin['f'](); 

위 코드의 실행 결과는 어떻게 될까?

user.f() 에서는 'John'을, admin.f()에서는 'Admin'을 출력할 것이다.

최초에 sayHi가 정의될 때는 this.name이 undefined 였을 것이다. 가리키고 있는 this가 없기 때문이다.
그런데 이 sayHi는 user와 admin의 메소드가 되었고, 이 메소드가 실행될 때 this가 가리킬 대상이 정해졌다. user 메소드 sayHi의 this는 user를, admin 메소드 sayHi의 this는 admin 객체를 가리키게 되는것이다.

이렇게 신기할 수가 없다.

this with arrow function

신기한 것 하나 더 알아보자.

let user = {
  firstName: "보라",
  sayHi() {
    let arrow = () => alert(this.firstName);
    arrow();
  }
};

user.sayHi();

위 코드의 실행 결과는 어떻게 될까?

답은 '보라'이다.

화살표 함수에서 this를 사용하면, 이 this는 아무런 값을 가지고 있지 않게된다. 즉, 별도의 컨텍스트를 가리키는 this가 아닌 평범한 외부 함수(객체)를 가리키는 this를 사용하고 싶을 경우 화살표 함수를 이용하면 된다.

위의 코드에서는 화살표함수의 this가 자신이 선언된 sayHi()의 this를 사용하게 되고, sayHi()의 this는 자신이 선언된 user 객체를 가리키고 있다. 따라서 user 객체의 firstName에 접근할 수 있게 된다.

이제부터 예제를 통해 this를 조금 더 알아보도록 하자.

예제

let ladder = {
  step: 0,
  up() {
    this.step++;
  },
  down() {
    this.step--;
  },
  showStep: function() { // 사다리에서 몇 번째 단에 올라와 있는지 보여줌
    alert( this.step );
  }
};

ladder.up().up().down().showStep();

위의 코드가 정상 동작하도록 ladder 객체를 수정해보자.

답은 다음과 같다.

let ladder = {
  step: 0,
  up() {
    this.step++;
    return this;
  },
  down() {
    this.step--;
    return this;
  },
  showStep: function() { // 사다리에서 몇 번째 단에 올라와 있는지 보여줌
    alert( this.step );
  }
};

각 메소드에서 this를 return하도록 하면 그 메소드의 this가 참조하는 외부 객체인 ladder가 반환된다. 즉, 문제의 코드에서 각 메소드가 실행될때마다 반환된 ladder 함수에 대해 재차 메소르를 호출하는 체이닝을 구현할 수 있게 된다.

마무리

  • this 란?
    • JS에서 객체를 참조할 수 있는 키워드이다. this가 메소드에서 호출되면 스 메소드를 포함하고 있는 객체를 참조할 수 있게 된다. this가 가리키는 명확한 값은 정확히 런타임에 결정된다. 즉 this를 사용하는 함수가 호출되기 전까지는 this의 값이 결정되지 않는다. 만약 해당 함수를 호출했을 때의 컨텍스트에 의해 정해진 this값을 사용하고싶지 않다면, 화살표함수를 이용해야한다. 화살표함수는 this값을 갖지 않으므로, 자신이 사용된 외부 함수의 this 값을 사용하게 된다.

this에 대해서 더 정확히 알기 위해선 context에 대한 이해가 필요한데, JS의 context는 별도의 게시글에서 다루도록 하겠다.

참고자료

https://ko.javascript.info/object-methods

profile
원리를 좋아하는 개발자

0개의 댓글