javascript

[javascript] 함수 call, apply, bind의 차이

미 성 2024. 3. 2. 01:55

참고 : 학습 페이지 (inflearn.com)

 

안녕하세요. 오늘은 자바 스크립트 함수 call(), apply(), bind() 에 대하여 알아보겠습니다.

이 세 함수는 자바스크립트에서 제공하는 기본 메소드입니다. 이들을 한 마디로 정리하자면

 


함수의 this 값을 지정할 수 있는 메소드

 

 

입니다. 글자만으로는 잘 와닿지 않으니 바로 코드를 보면서 이야기 해 보겠습니다.

 


 

 

이름을 출력해주는 showname이라는 함수가 보입니다. 이 함수는 객체 내부에 존재하는 함수인 메소드가 아닌, 독립적으로 존재하는 함수일 뿐이므로 현재 this.name에서의 this는 아무것도 가리키고 있지 않습니다. 

 

showname 함수 바로 위에는 이 함수와는 아무런 연결고리가 없어 보이는 mimi 객체가 있습니다.

 

오늘 배울 함수들을 통해 우리는 이처럼 아무런 연결고리가 없던 한 객체와 한 함수를 연결짓는 일을 하게 될 것입니다.

 


 

 

1. call ()

 

call () 의 첫 번째 인수 : 가리키게 할 객체

              추가적인 인수(들) : 함수를 호출할 때 필요한 매개변수(들) 

 

위 사진을 이어서 설명하겠습니다. 코드  showname.call(mimi); 는 showname 함수를 호출하며 그에게 " 객체 mimi를 가리키거라. " 라고 명령하는 것과 같습니다. 그러므로 함수 showname 속의 변수 this는 지금부터 객체 mimi를 가리키게 됩니다.

 

결론적으로 이 코드를 통해 "객체 mimi를 가리키는 함수 showname()"이 호출되므로, 출력값은 "mimi"가 되겠네요.

 

 

 

앞서 살펴본 것과 같은 경우 뿐만 아니라, 

이미 다른 객체 내에서 그 객체의 메소드로 존재하는 함수 또한 같은 방법으로 호출해 낼 수 있습니다. 

 

다른 객체에 속한 함수를 호출

 

아까는 밖에 있던 showname 함수가 이번에는 객체 안에 메소드로 들어가 있습니다. 그러므로 이번에는 함수를 호출할 때 mimi.showname코드가 선행되어야겠죠. (객체 mimi의 메소드이므로.) 그 후 바로 뒤에 ".call()"만 붙여주면 됩니다. 이번에는 객체 mike를 괄호에 넣었네요. 보시다시피 call()함수는 어떤 종류의 함수에게도 모두 적용이 가능합니다.

 

출력 결과는 "mike"가 되겠네요.

 

마지막 줄 코드를 조금 더 가독성 있게 하자면 아래와 같이 함수를 가리키는 새로운 변수를 정의해도 좋습니다.

 

let fn = mimi.showname;

fn.call(mike); 

 

 


 

 

2. apply ()

 

apply () 의 첫 번째 인수 : 가리키게 할 객체

              *두 번째 인수부터는 모두 배열에 넣어야 함. *

ex . apply( "객체이름", ['x1','x2',...] )

 

  " call 함수는 매개변수를 직접 받지만, apply 함수는 매개변수를 배열로 받음 "

 

이 사실 하나를 제외하고는 모든 방식과 기능이 call과 완전히 같다고 보시면 됩니다.

*이 달린 세 문장의 차이점을 살펴봅시다.

 

우선 Math.min()은 괄호 안에 든 요소들 중 가장 작은 숫자를 출력해 주는 메소드입니다.

( 수학과 관련된 다양한 메소드, 속성들이 들어있는 Math라는 객체가 있다. ** 중요)

 

Math.min.call(null,...nums)Math.min(...nums)와 동일한 결과를 출력합니다.

배열을 요소 하나하나로 받아내며 비교하기 때문에 이 둘의 경우 전개구문을 사용하여 "...nums"라 적습니다.

 

그러나 Math.min.apply(null,nums)를 보시면 이 함수호출에서의 매개변수만 "nums"임을 알 수 있는데,

앞서 말했듯 apply함수는 매개변수를 배열로 받아내는 함수이기 때문입니다.

( call과 apply 첫번째 매개변수를 null로 둔 것은 현재는 가리킬 객체가 필요하지 않기 때문 )

 

 


 

 

3. bind ()


마지막으로 살펴 볼 bind 함수는 ,

" 함수의 this 값(즉 함수가 가리키는 객체)을 영구히 바꿀 수 있는 함수 " 가 되겠습니다.

 

조금 헷갈릴 수 있는 마지막 코드를 함께 살펴보겠습니다.


위 코드에는 현재 name 속성 하나만을 가진 mimi 객체 하나와,

두 개의 인수를 전달받아 각각을 변수 year과 job에 할당해주는 역할을 하는 update 함수 하나가 있습니다.

 

바로 그 아래의 코드인 const mimiupdate = update.bind(mimi); 를 봅시다.

이 코드를 보고 얻을 수 있는 사실은 , " mimiupdate는 update함수이되, mimi 객체를 가리키는 함수다. " 입니다.

이로서 this.year과 this.job의 "this"는 모두 객체 mimi를 가리키게 되겠네요. 

this.year과 this.job에 할당되는 값들은 이제 모두 객체 mimi의 속성들로 업데이트 됩니다.

( mimi 객체에 기존에 있던 속성인 name은 당연히 그대로 존재하고 있습니다. )

 

마지막 줄의 mimiupdate(2001,"student"); 코드는 year, job 두 인수를 mimiupdate에 전달하는 모습입니다.

즉, 객체 mimi의 year, job 속성에 담길 값들을 전달받았다고 할 수 있겠죠.


위 코드 작성 후 최종적으로

console.log(mimi); 를 찍어보면, 출력값은

 

{
  "name": "mimi",
  "year": 2001,
  "job": "student"
}

 

최종 mimi 객체의 모습이 나오게 됩니다.

 


 

 

" 함수가 객체를 가리키게 된다 "

= " 함수가 마치 그 객체에 속한 메소드가 된 것처럼 기능하도록 다시 태어난다 "

 

 

 

오늘은 자바 스크립트의 기본 메소드 call(), apply(), bind() 에 대하여 알아보았습니다.

읽어주셔서 감사합니다.