게시글

5만명이 선택한 평균 별점 4.9의 제로초 프로그래밍 강좌! 로드맵만 따라오면 됩니다! 클릭
강좌24 - JavaScript - 9년 전 등록 / 8년 전 수정

함수의 메소드와 arguments

call, apply, bind

안녕하세요. 이번 시간에는 함수의 메소드에 대해 알아보겠습니다.

초보 강좌에서 숫자, 배열, 문자열에 대한 메소드에 대해서만 알려드렸죠. 함수에도 기본 메소드가 있습니다. 하지만 초보 강좌에서 다루지 않은 이유는... 어렵기 때문입니다. 사실 앞으로 한 번도 못 볼 수도 있고 안 쓸 수도 있어요. 하지만 중요하기 때문에 다루고 갑니다.

함수의 메소드 중 중요한 건 call, apply, bind입니다.

call과 apply부터 살펴보겠습니다. 원래 함수는 선언한 후 호출해야 실행되죠. 호출하는 방법으로는 함수 뒤에 ()를 붙이는 것과, call 그리고 apply하는 방법이 있습니다.

var example = function (a, b, c) {
  return a + b + c;
};
example(1, 2, 3);
example.call(null, 1, 2, 3);
example.apply(null, [1, 2, 3]);

보면 call은 보통 함수와 똑같이 인자를 넣고, apply는 인자를 하나로 묶어 배열로 만들어 넣는 것을 알 수 있습니다. 그렇다면 call과 apply가 공통적으로 가진 null 인자의 역할은 뭘까요?

바로 this를 대체하는 겁니다.

var obj = {
  string: 'zero',
  yell: function() {
    alert(this.string);
  }
};
var obj2 = {
  string: 'what?'
};
obj.yell(); // 'zero';
obj.yell.call(obj2); // 'what?'

마지막 줄에서 obj.yell.call(obj2)로 this가 가리키는 것을 obj에서 obj2로 바꾸었습니다. yell은 obj의 메소드인데도 zero 대신에 what?이 alert되었습니다. 즉 다른 객체의 함수를 자기 것마냥 사용할 수 있는 겁니다.

실행 컨텍스트 강좌에서 this는 기본적으로 window라고 했었죠. 몇 가지 방법으로 window를 다른 것으로 바꿀 수 있는데요. call, apply, bind에서 첫 번째 인자로 다른 것을 넣어주는 게 this를 바꾸는 방법 중 하나입니다.

위 메소드들을 쓰는 예로, 함수의 arguments를 조작할 때 사용합니다. arguments는 함수라면 처음부터 갖고 있는 숨겨진 속성인데요. 바로 함수에 들어온 인자를 배열 형식으로(배열은 아닙니다. 유사 배열이라고 부릅니다.) 반환합니다.

function example() {
  console.log(arguments);
}
example(1, 'string', true); // [1, 'string', true]

생긴 건 배열이지만, 배열이 아니라 유사 배열이기 때문에, 배열의 메소드는 쓸 수 없습니다.

function example2() {
  console.log(arguments.join());
}
example2(1, 'string', true); // Uncaught TypeError: arguments.join is not a function

에러가 발생하죠? arguments는 모양만 배열이지 실제 배열이 아니라서 배열의 메소드를 쓰면 에러가 발생합니다. 이 때 바로 call이나 apply가 효력을 발휘합니다.

function example3() {
  console.log(Array.prototype.join.call(arguments));
}
example3(1, 'string', true); // '1,string,true'

이제 제대로 작동하네요. 배열의 프로토타입에 있는 join 함수를 빌려 쓰는겁니다. this는 arguments를 가리키게 하고요. join 외에도 slice, concat 등등 모든 메소드를 이 방식으로 사용할 수 있습니다.

이제 bind 함수에 대해 알아보겠습니다. bind 함수는 함수가 가리키는 this만 바꾸고 호출하지는 않는 겁니다. 위의 예를 재사용하겠습니다.

var obj = {
  string: 'zero',
  yell: function() {
    alert(this.string);
  }
};
var obj2 = {
  string: 'what?'
};
var yell2 = obj.yell.bind(obj2);
yell2(); // 'what?'

obj.yell.bind(obj2) 했더니 yell 함수의 this가 obj2로 바뀌었습니다. 즉 call이나 apply와 비슷하지만 호출은 하지 않지 않고 함수만 반환하는 겁니다. call(this, 1, 2, 3)bind(this)(1, 2, 3)과 같죠.

다음 시간에는 객체의 복사에 대해서 알아보겠습니다.

조회수:
0
목록
투표로 게시글에 관해 피드백을 해주시면 게시글 수정 시 반영됩니다. 오류가 있다면 어떤 부분에 오류가 있는지도 알려주세요! 잘못된 정보가 퍼져나가지 않도록 도와주세요.
Copyright 2016- . 무단 전재 및 재배포 금지. 출처 표기 시 인용 가능.
5만명이 선택한 평균 별점 4.9의 제로초 프로그래밍 강좌! 로드맵만 따라오면 됩니다! 클릭

댓글

8개의 댓글이 있습니다.
5년 전
bind 는 이름이 직관적이네요 👍
apply는 인자를 배열로 만들어 넣는다는 것을 제외하면 call과 같은 거죠?
5년 전
네 apply와 call은 그 점 빼고는 똑같습니다. 저는 apply의 a와 array의 a가 같다는 점으로 외웠네요 ㅋㅋ
5년 전
너무 이해하기 쉬운 설명으로..잘 배우고 가요. 머릿속으로 이해했는데, 어디에 적용 할 수 있을까 생각해 봐야겟습니다.
5년 전
Array.prototype.join.call(arguments) 는 실행이 되는데
Array.prototype.join('').call(arguments) 이런식으로 seperator넣으면 실행이 불가능한데 방법이 없을까용?
5년 전
Array.prototype.join.call(arguments, " ") 뒤에다가 인자로 넘기면 실행이 되는군요! 근데 왜그런지는 모르겠네용...
5년 전
첫 번째 인수가 this고, 그 뒤의 인수부터는 join의 인수라서 그렇습니다.
6년 전
좋은글 감사합니다. 근데 join함수의 내부 구현이 좀 궁금하네요!. 어떻게 join함수의 this를 arguments로 했다고 join이 되는 걸까요? 내부적으로 this가 배열인지 검사하고 아니라면 배열로 만든 다음에 join하는걸까요?
6년 전
그냥 인덱스가 있는지 확인하고 합치는 걸 겁니다(유사배열도 0 1 2 인덱스는 있으니까요)
6년 전
답변 감사합니다 :D
7년 전
안녕하세요 이 블로그가 최고인것 같습니다... 다름이 아니라 제가 궁금한게 있어서 이렇게 댓글로 여쭤보려구요. 블로그에 포스팅 하신 자바스크립트 관련된 글들이, 언어의 기본적인 문법보다는 더 깊은 내용(실행컨텍스트, 이벤트루프, 디자인패턴 등등)이라고 생각합니다. 혹시 zerocho님 께서는 이런 내용들을 어떤것들을 참고하며 공부하셨는지 궁금합니다.
7년 전
mdn이나 다른 블로그(해외 위주)들 참고했습니다. 직접 응용해서 코딩해보기도 했고요. 그리고 블로그 포스팅하면서 글로 정리하는 것 자체가 많은 도움이 됩니다.
7년 전

function Parent() {
this.a = 20;
this.b = "김길동";
}

function Child() {
Parent.call(this);
this.c = 100;
this.d = "홍길동"
}

console.dir(new Child());

제가 call에 대한 이해가 부족한걸까요?
this의 이해가 부족한걸까요?
콘솔로 찍었얼때는 child객체에는
a, b, c, d 모두 가지고 있네요..
이해가 어렵습니다.
7년 전
Parent.call(this)는 Parent의 생성자를 실행하는데 this만 Child의 this를 쓰는 것입니다. Parent 생성자의 this.a와 this.b는 Child의 것이 되는 것이죠.
7년 전
답변 감사합니다. 아직도 뭔가 알송달송 해요.ㅎㅎ'
8년 전
call bind apply 쉽게 알 수 있었습니다 감사합니다
9년 전
하이루~^^ 5눌 ┐├입h@N 조가입니다. 헷갈리는 내용이었는데 정말 동무이 많이 됐어요. 쥔장님 복 많이 받으세요