JavaScript의 this
-
2024년 06월 18일
시작하며
안녕하세요. 서버 엔지니어 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의 참조 대상을 변경하여 함수를 호출하는 방법을 소개하도록 하겠습니다.