본문 바로가기
Learn to Code

[JS] apply, call, bind

by CEOSEO 2021. 10. 21.
728x90
반응형

 

 

apply(), call(), 그리고 bind()는 모두 함수의 프로토타입 메소드이다. 

 

apply, call, 그리고 bind... 함수 프로토타입 메소드로 존재한다는 것은 알고 있었지만 실상 많이 써보지 못해서 사용법을 숙지하지 못하고 있던 함수들이었다. 그나마 bind 같은 경우엔 리액트의 class component에서 필수로 사용해줘야 하는 메소드라서 몇 번 사용해봤지만, 그 리액트에서 마저도 class component가 아닌 function component만 계속 사용해왔기에 사용법을 잊고 있었다. 🥲 그렇게 어느덧 이 셋은 나의 기억 속에서 잊혀진 메소드들이 되어버렸다...

 

하지만 최근 이 셋을 다시 돌아봐야겠다는 굳은 결심(!!!)이 들었고, 다시 한번 이들을 활용할 수 있는 능력을 각성(?)하기 위해 정리한 내용을 아래에 공유하고자 한다.

 

 

 

 

 

apply와 call

apply와 call은 굉장히 비슷하기 때문에 한 카테고리에 묶었다. 이 두 메소드는 유사 배열 객체인 arguments 객체에 배열 메소드를 사용하고 싶은 경우에 사용하면 된다. arguments 객체함수를 호출할 때 전달된 인수들을 담고 있는 유사 배열 객체이다. 유사 배열 객체이기 때문에 본연의 모습 그대로 배열 메소드를 사용할 수 없다. 그래서 arguments 객체에 배열 메소드를 사용하고 싶을 경우 apply나 call을 사용해주는 것이다.

 

apply 함수에 전달될 인수 리스트(argument list)를 받음
call 인수들의 단일 배열(a single array of arguments)을 받음

 

apply와 call 메소드가 bind와 크게 다른 방식으로 작동하는 점은 바로 이 둘은 함수를 호출한다는 것이다. apply와 call은 (1) 함수를 호출하면서 (2) this에다가 첫번째 인수로 전달한 특정 객체를 바인딩한다. 이와 다르게, bind는 함수를 호출하지 않으며, 단지 this로 사용할 객체만 전달할 뿐이다.

 

apply()와 call()은 함수에 인수를 전달하는 방식만 다를 뿐 동일한 일을 한다. apply엔 인수의 리스트를 전달하며, call엔 인수들을 개별적으로 추가하면 된다. 

 

func.protype.apply(this값, [인수1, 인수2, 인수3, ...])
func.prototype.call(this값, 인수1, 인수2, 인수3,...)

 

이와 유사한 기능으로 여길 수 있는 문법으론 ES6에 추가된 rest parameter가 있다.

2021.03.23 - [Learn to Code] - [JS] Rest 파라미터 vs. 스프레드 문법(Spread syntax)

 

[JS] Rest 파라미터 vs. 스프레드 문법(Spread syntax)

Rest parameter와 스프레드 문법은 모양이 똑같아서 ( ... ) 굉장히 혼돈하기 쉽다. 하지만 둘은 엄연히 다른 것이다. 사실, 그 의미를 살펴보면 서로 반대의 개념을 갖고 있다고 볼 수 있다. Rest paramete

seo-tory.tistory.com

 

 

// call()을 사용한 경우
function convertArgsIntoArray1 () {
  const arr = Array.prototype.slice.call(arguments)
  return arr
}

// Rest parameter를 사용한 경우
function convertArgsIntoArray2 (...rest) {
  return rest
}

console.log(convertArgsIntoArray1(1,2,3)) // [1, 2, 3]
console.log(convertArgsIntoArray2(1,2,3)) // [1, 2, 3]

 

 

bind

bind는 원치 않는 this 바인딩 문제를 해결할 때 사용한다.

 

자바스크립트의 this는 다른 변수나 함수들과는 다르게 어디에서 정의되었는가에 따라 값이 정해지는 렉시컬 스코프(lexical scope)이 아닌 어떻게 호출되었는가에 따라 바인딩되는 dynamic scope을 따른다.

 

이에 따라 메소드에서 this는 메소드를 호출한 객체가 바인딩 되지만, 문제는 그 메소드 내부에서 중첩 함수 또는 콜백 함수에서 this를 사용하였을 경우엔 원했던 본연의 객체가 바인딩되지 않는다는 문제가 있다. this는 일반 함수로 호출된 콜백함수 내부에선 전역 객체 (window)를 가리키게 되기 때문이다. (strict mode이거나 Node.js 환경에선 undefined가 바인딩된다)

 

이러한 문제를 해결하기 위해, bind 메소드를 사용하여 메소드 내 중첩함수 또는 콜백함수에서 this 값을 개발자가 원하는 메소드를 호출한 객체에 묶어줄 수 있다 (말 그대로 bind를 해준다! 😃).

 

func.prototype.bind(this값, 인수1, 인수2, ...)

 

(물론, 메소드 내 콜백함수를 화살표 함수로 작성하면 굳이 bind()를 사용하지 않아도 this 문제를 더 간편하게 해결할 수 있긴 하다.)

 

 

 

 

728x90
반응형

댓글