안녕하세요. 이번 시간에는 함수의 메소드에 대해 알아보겠습니다.
초보 강좌에서 숫자, 배열, 문자열에 대한 메소드에 대해서만 알려드렸죠. 함수에도 기본 메소드가 있습니다. 하지만 초보 강좌에서 다루지 않은 이유는... 어렵기 때문입니다. 사실 앞으로 한 번도 못 볼 수도 있고 안 쓸 수도 있어요. 하지만 중요하기 때문에 다루고 갑니다.
함수의 메소드 중 중요한 건 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)과 같죠.
다음 시간에는 객체의 복사에 대해서 알아보겠습니다.

apply는 인자를 배열로 만들어 넣는다는 것을 제외하면 call과 같은 거죠?