Site Search

JavaScript의 this

시작하며

안녕하세요. 서버 엔지니어 GZR입니다.

JavaScript가 세상을 지배하고 있는 시대에서, 여러분은 JavaScript와 친숙하신가요? 이번에는 친해지기 어렵다고 느끼는 ‘this’에 대해 이야기해 보고자 합니다.

why ‘this’

왜 ‘this’라는 메커니즘이 구현되어 있는지 예제를 통해 살펴보겠습니다.

예제 1-1:

// 1-1
 <script>
 
  const obj = {
    oops: 1,
    method: function () {
      console.log(oops)
    }
  };
 
  obj.method() // Uncaught ReferenceError: oops is not defined
</script>

예제 「1-1」에서는 method가 실행될 때 먼저 함수 스코프에서 ‘oops’를 찾습니다.

찾을 수 없기 때문에 외부 스코프로 찾아가게 됩니다. 하지만 ‘obj = { … }’가 둘러싸고 있는 부분은 스코프가 아닙니다.

그 결과, 전역 스코프(window)에 도달하게 되고 전역 스코프에도 ‘oops’가 존재하지 않기 때문에 에러가 발생했습니다.

예제 1-2:

<script>

  let oops = 3

  // obj.methodに保存されているのは関数のアドレスに過ぎないため、 ここに定義し参照しても同じ
  function fn() {
    console.log(oops)
  }

  const obj = {
    oops: 1,
    method: fn
  };

  const obj2 = {
    oops: 2,
    method: fn
  };

  obj.method()    // 出力:3
  obj2.method()   // 出力:3

</script>

예제 「1-2」와 같이, 전역 스코프에 ‘oops’를 정의하면 둘 다 ‘3’이 출력됩니다. 그렇다면 어떻게 하면 fn 함수 실행 시 ‘참조 대상’을 고정하여 각 객체에 있는 ‘oops’ 값을 출력할 수 있을까요?

여기서 ‘this’가 등장합니다.

예제 1-3:

<script>
 
  let oops = 3
 
  function fn() {
    console.log(this.oops)
  } 
 
  const obj = {
    oops: 1,
    method: fn
  };
 
  const obj2 = {
    oops: 2,
    method: fn
  };
 
  obj.method()   // 出力:1
  obj2.method()  // 出力:2
 
</script>

this를 사용하면 호출한 객체에 대한 참조를 유지할 수 있기 때문에 “3”이 아닌 “1”과 “2”가 정확하게 출력되는 것을 볼 수 있습니다.

보충: this의 참조에 대하여

<script>

  const obj = {
    oops: 1,
    method:  function () {
      console.log(this.oops)
    }
  };
 
  obj.method()  // 出力:1
 
  var oops = 3
  let fn = obj.method
 
  fn()   // 出力:3

</script>

객체의 메서드를 다른 객체의 속성(이 예시에서는 window 객체의 fn)에 대입하면 this의 참조 대상도 자동적으로 window 객체로 변경됩니다.

그 결과, fn()의 출력 결과는 window 객체의 oops 값인 ‘3’이 됩니다.

참고로 또 다른 JS 트랩이 되는데, ‘var oops = 3’ 대신 ‘let oops = 3’ 또는 ‘const oops = 3’을 사용하면 출력 결과는 ‘undefined’가 됩니다. (var, let, const의 차이)

퀴즈

 //クイズ
<script>  

  var oops = 3
 
  const obj = {
    oops: 1,
    method: function () {
      console.log(this.oops)
    }
  };
 
  obj.method();  // 出力:1
 
  (obj.method = obj.method)()  // 出力:3
 
</script>

자신의 메서드에 동일한 메서드를 다시 대입했을 뿐인데 왜 출력 결과가 window의 ‘oops’ 값으로 변경되었을까요?

마지막 한마디

—”경계하고 있을 때는 버그가 찾아오지 않는 법이다”

끝까지 읽어주셔서 감사합니다. 다음 번에는 this의 참조 대상을 변경하여 함수를 호출하는 방법을 소개하도록 하겠습니다.


Category

Tag