자바스크립트의 'this' 키워드 이해하기

자바와 C++ 등을 주로 이용하던  개발자에게 자바스크립트의 this는 마치 '미지의 똥' 같은 느낌입니다. 습관대로 쓰다보면 어느새 질퍽하게 밟아버리곤 하죠. 결국 다시 한번 제대로 이해하기로 하고 웹을 너울거리다가 마침 좋은 자료를 발견하여 주요 액기스를 간추려 올려봅니다.

원본: Understanding the “this” keyword in JavaScript

우선 몇 가지 먼저 기억해 둘 사항들입니다:
  1. 자바스크립트에서 코드는 다음 세 가지 영역에서 수행됩니다: 
    • global 영역 
    • function 영역 
    • eval 영역
  2. this 키워드는 다음 두 가지 조건에 의해 값이 결정됩니다. 
    • 어떤 영역에서 수행되었는가 
    • 호출자가 누구인가 
  3. global 객체에 대해 이해해야 합니다: 
    • 자바스크립트가 구동 될 때에는 언제나 global 객체가 존재합니다. 브라우저에서는 window 객체가 그 역할을 하고 있고, node.js에서는 그냥 global object로 불리는 놈이 하나 있습니다.

자, 이제 this 키워드를 파악하기 위한 4가지 규칙을 살펴봅니다:

  1. 기본적으로 this는 global 객체이다.
    다음 3가지 케이스가 아닌 경우 언제나 global 객체를 가리킵니다.
  2. function 영역에서의 this는 부모 객체이다. 단, 그 부모의 자식으로서 불렸을 때에만. 
    • 이해가 쉬운 예제: increment 메소드 안의 this는 그 부모 객체인 counter를 가리키죠.
      var counter = {
        val: 0,
        increment: function () {
          this.val += 1;
        }
      };
      counter.increment();
      console.log(counter.val); // 1
      counter['increment']();
      console.log(counter.val); // 2
      
      
    • 아리까리한 예제: 하지만, 이 메소드를 counter의 자식으로서가 아니라 직접 호출하면 어떻게 될까요? this는 더 이상 counter가 아니라 global 객체가 됩니다. 
      var inc = counter.increment;
      inc();
      console.log(counter.val); // 2
      console.log(val); // NaN
      
      
  3. new 연산자로 생성된 function 영역의 this는 새로 생성된 객체 그 자신이다. 
    • 이해가 쉬운 예제: 여타의 언어와 비슷한 패턴이라 어렵지 않죠? 
      function F (v) {
        this.val = v;
      }
      var f = new F(“Woohoo!”);
      console.log(f.val); // Woohoo!
      console.log(val); // ReferenceError
      
      
    • 아리까리한 예제: new로 생성하지 않으면 그냥 보통의 함수를 호출하는 것과 다르지 않습니다. 따라서, this는 global 영역입니다. 
      var f = F(“Oops!”);
      console.log(f.val); // undefined
      console.log(val); // Oops!
      
      
  4. call 혹은 apply로 호출 된 함수의 경우 call, apply의 첫번째 인자로 명시 된 객체이다. 
    • 예제:
      var add = function (x, y) {
            this.val = x + y;
          },
          obj = {
            val: 0
          };
      add.apply(obj, [2, 8]);
      console.log(obj.val); // 10
      add.call(obj, 2, 8);
      console.log(obj.val); // 10
      


그 외에, eval 내에서 명시한 this는 조금 머리아픈 구석이 있습니다. 얼마나 최신의 ECMAScript 규약을 따르냐에 따라 브라우저끼리도 서로 다른 동작을 취하기 때문에 이 부분에 대해서는 상세한 참고 자료를 살펴 보실 것을 권장합니다. 원 사이트에서는 “Global eval. What are the options?”라는 문서가 도움이 될거라고 하네요.

제게는 위 문서가 명쾌하게 다가왔는데 여러분은 어떠실지 모르겠습니다.
혹시 제가 잘못 이해하고 있는 부분이 있다면 알려주시기 바랍니다.

0 comments:

댓글 쓰기

Powered by Blogger.

Popular Posts