함수를 어디서 어떻게 호출했는지에 관계 없이 this를 지정할 수 있는 call, apply, bind에 대해 짚고 넘어간다.
const bruce = { name : "Bruce" };
const madeline = { name : "Madeline" };
function greet(){
return `Hello, I'm ${this.name}! `;
}
greet(); // "Hello, I'm undefined!"
// this에 연결되는 파라미터가 없어서 어디에도 바인딩 안됨
greet.call(bruce); // "Hello, I'm bruce!" this는 bruce
greet.call(madeline); // "Hello, I'm Madeline!" this는 madeline
모든 함수에서 사용 가능하며 this를 특정 값으로 지정한다. 함수를 호출하면서 call을 마치 어떠한 객체의 메서드인 것처럼 사용할 수 있고 call의 첫 번째 파라미터가 this가 된다. 복수의 매개변수는 그대로 함수에 전달된다.
const bruce = { name : "Bruce" };
const madeline = { name : "Madeline" };
function update(birthYear, occupation){
this.birthYear = birthYear;
this.occupation = occupation;
}
update.call(bruce, 1949, 'singer');
update.call(madeline, 1942, 'actress');
update함수에서 call을 통해 name, birthYear, occupation이 지정된다.
const bruce = { name : "Bruce"};
const madeline = { name: "Madeline"};
function update(name, birthYear, occupation){
this.birthYear = birthYear;
this.occupation = occupation;
}
update.apply(bruce, [1949, 'singer']);
// bruce = { name: "Bruce", birthYear: 1949, occpupation: "singer"}
update.apply(madeline, [1942, 'actress']);
// madeline = { name: "Madeline", birthYear: 1942, occpupation: "actress"}
call과 아주 유사하고, 두 번째 파라미터부터 마지막까지는 하나의 배열로 묶어서 받는다.
배열의 최대 최소를 구할 때 apply를 활용할 수 있다.
const arr = [2, 3, -5, 15, 7];
Math.min.apply(null, arr); // -5
Math.max.apply(null, arr); // 15
Math.min(...arr);
Math.max(...arr);
// 확산 연산자(...)을 쓰면 조금 더 간결해진다.
주어진 배열을 확산 연산자로 apply에 전달할 수 있다.
const bruce = { name : "Bruce"};
const newBruce = [ 1940, "material artist"];
function update(name, birthYear, occupation){
this.birthYear = birthYear;
this.occupation = occupation;
};
update.call(bruce, ...newBruce);
const bruce = { name: "Bruce" };
const updateBruce = update.bind(bruce);
function updateBruce(name, birthYear, occupation){
this.birthYear = birthYear;
this.occupation = occupation;
};
updateBruce(1904, "actor");
// bruce = { name: "Bruce", birthYear: 1904, occupation:"actor"
updateBruce.call("madeline", 1274, "king");
// bruce = { name: "Bruce", birthYear: 1274, occupation:"king"
한 번 bind로 this를 묶고 나면 영구적 값이 된다. call, apply를 통해 유동적으로 this값을 변경해야 하는 경우엔 bind가 에러를 일으킬 가능성이 있다. 따라서 this가 어디에 묶이는지 확실하게 체크해야 한다.