JS 시리즈 - 명시적 this 바인딩

개발자 하디·2022년 2월 8일
1

JAVASCRIPT시리즈

목록 보기
6/7

🙈INTRO

명시적으로 this를 바인딩 하는법을 알아보기 전에
JS 시리즈 - this
이전 글에서 확인 할 수 있듯이

  • 전역공간에서 this는 전역객체
  • 함수로서 호출하면 this는 전역객체 참조
  • 메서드로 호출한 경우 this는 메서드를 호출한 주체 참조
  • 콜백함수 내부에서의 this는 해당 콜백 함수의 제어권을 넘겨받은 함수가 정의한 바에 따른다.
    (정의하지 않은 경우에는 this는 전역객체를 참조)
  • 생성자 함수의 this는 생성될 인스턴스를 참조

이렇게 명시적 this 바인딩을 하지 않는 한 늘 성립한다고 하였다.

그럼 명시적으로 this 바인딩을 하는 방법에는 무엇이 있을까?

  • call
  • apply
  • bind

이렇게 총 3가지의 메서드가 있다.

하나하나씩 차례대로 알아보겠다.

1. call

  • call 메서드는 메서드의 호출 주체인 함수를 즉시 실행하도록 하는 명령입니다.

Function.prototype.call(thisArg[, arg1[, arg2[, ...]]])

  • 이렇게 첫번째 인자값으로 this가 참조할 주체를 받는다.(thisArg)
  • 이후의 인자들은 호출할 함수의 매개변수가 됩니다.(arg1, arg2....)
const 함수 = function (a, b){
    console.log(this, a, b);
}

함수(1,2); // (1)
함수.call({name:'coder_h'}, 1,2); // (2)

(1) 브라우저 환경이면 windw 1 2 노드 환경이면 global 1 2가 출력 될것입니다.
(2) {name:'coder_h'} 1 2 가 출력이 된다.

😀 이렇게 알 수 있듯이 말그대로 (1)함수로서 호출을 한다면 런타임 환경에 따라 다르겠지만 this는 전역객체를 참조하지만
(2) call 메서드를 이용하여 this에 바인딩될 주체를 인자로 넘겨준다면 함수로서 호출을 하더라도 전역객체가 아닌 this값으로 넘긴 매개변수를 참조하게 된다.

2. apply

  • apply 메서드는 call 메서드와 기능적으로는 완전히 동일합니다.
  • 하지만 apply 메서드는 두번째 인자를 call 메서드와 달리 배열로 받아 그 배열의 요소들이 호출할 함수의 매개변수로 지정합니다.

Function.prototype.apply(thisArg[, argsArray])

  • 첫번째 인자값으로 this가 참조할 주체를 받는다. (thisArg)
  • 두번째 인자 배열은 호출할 함수의 매개변수로 지정이 된다. ([argsArray])
const 객체 = {
    메서드 : function(a,b,c){
        console.log(this, a, b, c);
    }
};

객체.메서드(1,2,3); // (1)
객체.메서드.apply({name:'coder_h'},[4,5,6]); // (2)

(1) 메서드로 호출을 하면 this는 메서드를 호출한 주체를 this가 참조하기 때문에 { '메서드': [Function: 메서드] } 1 2 3 가 출력이 됩니다.

(2) 그러나 apply 메서드를 이용하여 명시적으로 this가 참조할 대상을 첫번째 인자로 넘기고 두번째 인자로 배열을 호출할 함수의 매개변수로 넘기게 된다면 예상하시다시피
{ name: 'coder_h' } 4 5 6 이 출력됩니다.

😎 즉, call과 apply의 기능은 같지만 단 한가지의 차이는 두번째 인자를 배열로 넘기냐의 차이입니다.

3. bind

  • bind 메서드는 call과 비슷하지만 즉시 호출하지 않고 넘겨받은 this와 인수들을 바탕으로 새로운 함수를 반환한다.

  • 다시 새로운 함수를 호출할 때 인수를 추가적으로 넘기면 그 인수들은 기존 bind 메서드를 호출할 때 전달했던 인수들의 뒤에 이어서 등록이 된다.

😝 즉, bind 메서드는 두 가지 목적을 지닌다.
1. this를 미리적용
2. 부분 적용 함수를 구현

Function.prototype.bind(thisArg[, arg1[, arg2[, ...]]])

const 함수 = function(a,b,c,d){
    console.log(this,a,b,c,d);
}

const 바인드함수1 = 함수.bind({name:'corder_h'})
바인드함수1(1,2,3,4); // (1)

const 바인드함수2 = 함수.bind({name:'hazzang'}, 1, 2); // (2)
바인드함수2(3,4); // (3)

(1) 위에서 보시다시피 bind는 두가지 목적을 지닌다고 하였는데 첫번째의 예시이다. bind메서드를 사용하여 this만 지정한 후 새로운 함수를 만든다. 이 함수를 호출하면 지정한 주체와 호출할때 넘긴 매개변수가 출력된다. ({ name: 'corder_h' } 1 2 3 4)

(2),(3) 두번째는 두번째 예시인 부분 적용 함수를 구현했다.
위에 bind 메서드 소개시에 새로운 함수를 호출할 때 인수를 추가적으로 넘기면 기존 bind 메서드를 호출할 때 등록한 인수들 뒤에 등록이 된다고 하였다. 처음에는 bind메서드를 이용하여 1,2를 넘겨주었고 나중에 새로운 함수를 호출할 때 넘긴 인수 3,4가 지정한 this와 함께 차례대로 출력되는 것을 확인할 수 있다. ({ name: 'hazzang' } 1 2 3 4)

😚 이렇게 bind 메서드는 this를 미리적용 하는 것과 부분 적용 함수를 구현 이라는 두가지 목적을 가지고 있고, call 메서드 처럼 즉시 호출하는 것이 아닌 새로운 함수를 반환을 한다.

🙉정리

  • call, apply 메서드는 this를 명시적으로 지정하면서 함수 또는 메서드를 호출
  • bind 메서드는 this 및 함수에 넘길 인수를 일부 지정해서 새로운 함수를 만듬 (즉시 호출 X)

참고 :
1. 코어자바스크립트
2. 인프런 - 코어자바스크립트

profile
기록 저장소

1개의 댓글

comment-user-thumbnail
2023년 1월 5일

this에 대해 이해하는데 많은 도움이 됐습니다
유익한 포스팅 감사합니다 :)

답글 달기