함수를 선언하고 호출하는 방법에는
함수 뒤에 (), call, apply
let 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는 인자를 배열로 만들어 넣는다.
여기서 null의 역할은 this를 대체하는 것.
let obj = {
string: '주영',
yell: function() {
alert(this.string);
}
};
let obj2 = {
string: '선영'
};
obj.yell();
// '주영'
obj.yell.call(obj2);
// '선영'
obj1.yell()을 obj2.yell()로 바꾼 효과
call이 this가 가리키는 것을 obj에서 obj2로 바꿈.
call로 this를 정의해주면 다른 객체의 파라미터나 메소드를 자기 것처럼 사용할 수 있다.
.call(this, parameter1, paremeter2 ...)
.apply(this, []);
this는 기본적으로 전역객체의 window로 정해져 있다.
call, apply, bind에서 첫 번째 인자로 다른 값을 넣어주면 this를 바꿀 수 있다.
이 메소드들은 함수의 arguments를 조작할 때 사용.
arguments는 처음부터 갖고 있는 숨겨진 속성인데,
함수에 들어온 인자를 유사 배열로 반환한다.
function example() {
console.log(arguments);
}
example(1, 'string', true);
// [1, 'string', true]
실제 배열이 아니라서 배열의 메소드를 사용할 수 없는데,
이 때 call, apply가
function example2() {
console.log(Array.prototype.join.call(arguments));
}
example2(1, 'string', true);
// '1,string,true'
배열의 프로토타입에 있는 join 함수를 빌려쓸 수 있다.
먼저 join()으로 배열을 문자열로 반환하려고 한다.
함수 인자로 값들을 넘긴다. arguments로 유사배열을 받지만, join()이 안된다.
그래서 프로토타입 메서드 Array.prototype.join()을 불러오고
그 뒤에 .call()로 join 함수를 조작합니다.
call(arguments)로 this가 유사배열을 가리키게 한다.
(join 외에도 모든 메소드를 이 방식으로 사용할 수 있다.)
apply() 메소드의 대표적인 용도는 arguments 객체와 같은,
유사 배열 객체에 배열 메소드를 사용하는 경우.
Array.prototype.slice.apply(arguments)는,
"Arrray.prototype.slice() 메소드를 호출하고, this는 arguments 객체로 바인딩해라"라는 의미가 된다.
bind 함수는 함수가 가리키는 this만 바꾸고 호출하지는 않는다.
this를 정의하고 나서 그 함수를 복사해 새로운 함수를 만들어 리턴하는 것.
let obj = {
string: '주영',
yell: function() {
alert(this.string);
}
};
let obj2 = {
string: '선영'
};
let yell2 = obj.yell.bind(obj2);
yell2();
// '선영'
obj.yell.bind(obj2)();
// '선영'
즉, call, apply와 비슷하지만 호출은 하지 않고 함수만 반환한다.
call(this, 1, 2, 3)은 bind(this)(1, 2, 3)과 같다.
call, apply, bind는 그냥 참조하는 함수 안의 this를 바꿔서
마치 해당 함수가 어느 객체 안에 있게 할 수 있다.
let obj = { ... , yell(){} };
let obj2 = { ... };
obj.yell.call(obj2); === obj.yell();
let arr = [ ... ];
Array.prototype.join.call(arr) === [].join.call(arr) === arr.join();
call, apply는 바로 적용을 하지만, bind는 적용하지 않고 반환한다.
하지만 binde()()하면 call처럼 사용할 수 있다.
apply는 인수를 배열로 받는 call이다.
여러 개의 인수를 적용하고 싶은데, 상수가 아닌 변수로 적용하려고 할 때 쓰인다.
ex) (1, 2, 100, 200) 같은 인수를 주려고 할 때,
상수가 아닌 변수나 묶음으로 관리하며 주고 싶을 때 [1, 2, 100, 200]을 주고
apply하면 마치 call(arr, 1,2,100,200)을 주는 것과 같다.