개발 기술/개발 이야기

call, apply, bind의 차이

by GicoMomg (Lux) 2021. 11. 25.

이 포스팅은 call(), apply(), bind()에 대해 소개하고 있습니다.

  • js에서는 함수 호출 방식과 상관없이 this에 접근할 수 있다.
  • 그렇다면 this를 우리가 원하는 객체로 지정할 수는 없을까?
  • 이번시간에는 커스텀 this를 지정할 수 있는 세 함수에 대해 알아보자!

1. call(), this를 맘대로 지정할 수 있지

  • call()은 모든 함수에서 사용가능하며, this를 특정 객체로 지정할 수 있다.
  • 아래 예시는 printDogAge()에서 dogage값을 출력하려고 한다.
const dog = {
  age: 12
}

function printDogAge() {
  console.log(this.age)
}
  • 그런데 printDogAge()를 호출해보면, 기대한 값은 나오지 않고 undefined가 출력된다.

왜 dog의 age가 출력되지 않는걸까?

  • dogage가 출력되지 않은 이유는 현재 thiswindow를 가리키고 있기 때문이다.
  • 함수는 별도의 처리를 하지 않으면 thiswindow 객체를 가리킨다.

  • 그렇다면 thisdog를 가리키도록 하려면 어떻게 해야할까?
  • 바로 call()을 사용하는 것이다.
  • 호출함수.call(this로_지정할_대상)을 하면 함수에서 특정 객체를 this로 지정할 수 있다!
const dog = {
  age: 12 
}
function printDogAge() {
  console.log(this.age)
}
printDogAge.call(dog)    // 12
  • call()을 사용하면, 우리가 기대한 값(12)이 나오게 된다.

여기서 잠깐! 그럼 매개변수를 전달하고 싶으면 call은 어떻게 써야할까?

  • call()의 첫 번째 인자가 this로 지정할 객체라면, 두 번째 인자부터는 함수에 넘겨줄 매개변수를 지정할 수 있다.
const dog = {
  age: 12 
}
function printDogAge(name, location) {
  console.log(this.age, name, location)
}
printDogAge.call(dog, 'mike', 'seoul')    // 12, mike, seoul



2. apply(), call과 유사하지만 배열을 인자로...

  • apply()call()과 유사하지만, 매개변수 처리 방법에서 차이가 있다.
  • 앞서 살펴봤듯이 call()은 일반적인 함수처럼 매개변수를 받지만, apply()는 배열형태의 매개변수를 받는다.
const dog = {
  age: 12 
}
function printDogAge(name, location) {
  console.log(this.age, name, location)
}
printDogAge.apply(dog, ['mike', 'seoul'])   // 12, mike, seoul

그런데 배열 매개변수를 받는 게 좋은 상황이 있나요?

  • Math.min()를 예시로 보자!
  • Math.min()은 인자로 넘긴 값 중 제일 작은 값을 리턴해주는 함수이다.
const minValue = Math.min(12, 200);
console.log(minValue)

  • 그런데 만약 우리가 배열에서 제일 작은 값을 알고 싶다면 어떻게 해야할까?
  • Main.min()을 사용하는 경우, spread 연산자를 사용해야 한다.
const arr = [1,23,4,55,231];
const minValue = Math.min(...arr);
console.log(minValue)     // 1

  • 하지만 배열 그대로 넘고 싶다면? 이 경우 apply()를 사용하는 것이다.
  • this로 지정할 객체가 없으므로 null로 지정하고, 두 번째 인자로 배열을 넣어주면 된다.
const arr = [1,23,4,55,231];
const minValue = Math.min.apply(null, arr);
console.log(minValue)    // 1



3. bind(), this를 영구적으로 변경할 수 있지

  • 우리는 앞서 call(), apply()에 대해 알아보았다.
  • 이 두 메소드는 함수에서 접근할 this객체를 변경할 수 있었다.
  • 하지만 커스텀 this를 영구적으로 가리키도록 할 수 없다.

만약 우리가 커스텀 this를 가리키는 함수를 만들고 싶다면 어떻게 해야할까?

  • 이 경우에는, bind()를 사용하면 된다.
  • bind()는 커스텀 this를 가리키는 함수를 생성할 수 있게 해준다.
  • 앞선 dog, printDogAge()를 예시로 살펴보자!
const dog = {
  age: 12 
}
function printDogAge(name, location) {
  console.log(this.age, name, location)
}

  • 우리는 printDogAge()thisdog를 영구히 가리키게 하고 싶다.
  • 먼저, 함수.bind(커스텀_this_객체)방식으로 printDogAge를 특정 변수에 담는다.
const print = printDogAge.bind(dog);
  • 이 코드는, printDogAge()thisdogprint함수를 생성한다는 의미이다.

  • 이제 print에 인자를 넣어 호출해보면, 우리가 원하던 결과가 나오게 된다.
print('lala', 'USA')  //12 lala USA

이외에도 bind()는 특정 함수를 더 짧게 만드는 용도로 사용할 수 있다.

  • js에서 우리는 데이터의 형태를 출력할거나 테스트할 때 console.log를 자주 사용한다.
  • 하지만 이 console.log를 자주 쓰는 상황에서는 이 구문도 길게 느껴질 수 있다.
  • 이 경우, bind()를 사용해 짧은 함수로 만들 수 있다.
const log = console.log.bind(document);

log('test');      // test
log('helloooooo') // helloooooo





오늘 우리는 call, apply, bind에 대해 알아보았다.
call()은 커스텀 this를 지정할 수 있었고, apply()는 call()과 유사하지만 인자로 배열을 받는다는 점에서 차이가 있었다. 마지막으로 bind()는 커스텀 this를 영구히 가지는 함수를 만들 수 있었다.


반응형

댓글