게시글

강좌24 - JavaScript - 4년 전 등록 / 3년 전 수정

함수의 메소드와 arguments

call, apply, bind
조회수:
0

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

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

함수의 메소드 중 중요한 건 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)과 같죠.

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

투표로 게시글에 관해 피드백을 해주시면 게시글 수정 시 반영됩니다. 오류가 있다면 어떤 부분에 오류가 있는지도 알려주세요! 잘못된 정보가 퍼져나가지 않도록 도와주세요.
Copyright 2016- . 무단 전재 및 재배포 금지. 출처 표기 시 인용 가능.

댓글

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

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 모두 가지고 있네요..
이해가 어렵습니다.
2년 전
Parent.call(this)는 Parent의 생성자를 실행하는데 this만 Child의 this를 쓰는 것입니다. Parent 생성자의 this.a와 this.b는 Child의 것이 되는 것이죠.
2년 전
답변 감사합니다. 아직도 뭔가 알송달송 해요.ㅎㅎ'
3년 전
call bind apply 쉽게 알 수 있었습니다 감사합니다
4년 전
하이루~^^ 5눌 ┐├입h@N 조가입니다. 헷갈리는 내용이었는데 정말 동무이 많이 됐어요. 쥔장님 복 많이 받으세요