[JS] this에 관하여

Jeong Choi(최현정)·2024년 6월 3일
0

자바로 개발을 했을 당시에 내가 알던 this는 현재 객체만을 참조한다 정도였다. 그렇기 때문에 자바스크립트로 개발을 할 때도 this가 그런건가 보다.. 라고 생각을 했는데 너무나도 동떨어진 생각이였다.

자바스크립트의 this는 자바와 달리 동적으로 this의 값이 달라져 생각보다 복잡하다. 나름 골치아픈 주제라 정리를 해보자.

우리가 잘 알고 있는 this

this란 자신이 속한 객체나 자신이 생성할 인스턴스를 가리키는 식별자를 참조할 수 있는 키워드다.

동적으로 값이 달라지는 this

위에서 언급했듯이, 자바스크립트에서 this는 계속 값이 달라진다. 그러면 언제 this의 값이 정해지는 걸까?

바로 함수가 호출되는 그 시점에 this의 값이 정해진다.

일반 함수 호출시 this의 값

const a = 'hello';

function abc() {
 console.log(this); // window 
 console.log(this.a); // hello
}

// 일반 함수 호출
abc(); 
  • 일반 함수로 호출시 this는 전역 객체인 window 객체에 바인딩
  • strict mode 적용된 경우 this는 undefined 바인딩

메서드 호출시 this의 값

const obj = {
    value: 10,
    method: function() {
		    console.log(this); // { value: 10, method: [Function: method] }
        console.log(this.value); // 10
    }
};

obj.method(); 
  • 메서드로 호출시 this는 메서드를 호출한 객체에 바인딩

생성자 함수 호출시 this의 값

const Obj = function() {
  console.log(this); // Obj
};

const foo = new Obj("foo"); 
  • 생성자 함수로 호출시 this는 생성자 함수가 생성할 인스턴스에 바인딩 → 생성한 객체 자신이 됨

화살표 함수 호출시 this의 값

const obj = {
    value: 10,
    method: function() {
		    console.log(this); // obj
        const innerMethod = () => {
            console.log(this); // obj
            console.log(this.value); // 10
        };
        innerMethod();
    }
};

obj.method();

여기서 이상한 점이 보이는가? 분명히 innerMethod(); 로 호출 즉, 일반 함수 호출이기 때문에 전역 객체인 window 객체가 바인딩 되어야 하는데, innerMethod 함수의 this는 obj이다.
그 이유는 간단한데 innerMethod는 화살표 함수이기 때문이다. 화살표 함수는 예외를 가진다.

  • 화살표 함수자신의 this를 가지는 것이 아니라, 선언된 외부 스코프의 this를 바인딩

this의 값을 바꾸고 싶다면?

위의 내용들을 통해 함수의 종류에 따라 this의 값이 달라지는 것을 확인했다. 그렇다면 this의 값을 내가 원하는 대로 바꿀 수 있을까?

당연히 가능하다. 즉, this의 값을 강제로 바꿀 수 있다.
크게 3가지가 있는데 하나씩 살펴보자.

1) Function.prototype.apply

const obj = {
    value: 42
};

function printValue(a, b) {
		console.log(this); // obj { value: 42 }
    console.log(this.value); // 42
    console.log(a, b); // 1 2
}

printValue.apply(obj, [1, 2]);

2) Function.prototype.call

const obj = {
    value: 42
};

function printValue(a, b) {
		console.log(this); // obj { value: 42 }
    console.log(this.value) // 42
    console.log(a, b); // 1 2
}

printValue.call(obj, 1, 2);

여기서 apply와 call을 간단하게 정리해보겠다.

  • 공통점함수를 즉시 호출하면서 this 값을 설정하고 인자를 전달한다
  • 차이점
    apply는 호출할 함수의 인자를 배열로 전달한다
    call은 호출할 함수의 인자를 쉼표로 구분한 리스트 형태로 전달한다

3) Function.prototype.bind

const obj = {
    value: 42
};

function printValue(a, b) {
    console.log(this); // obj
    console.log(this.value); // 42
    console.log(a, b); // 1, 2
}

const boundFunction = printValue.bind(obj, 1);
boundFunction(2);

printValue.bind(obj, 1); 를 통해 printValue의 this를 obj로 바인딩하고, 첫 번째 인자가 1인 새로운 함수를 생성한다.
즉, bind 메서드는 함수의 this를 특정 객체로 고정하고, 일부 인자를 미리 설정할 때 유용하다.

  • bind 메서드나중에 호출할 수 있도록 this 값이 고정된 새로운 함수를 생성해 반환한다
profile
Node와 DB를 사랑하는 백엔드 개발자입니다:)

0개의 댓글