함수를 호출하면서 call() 과 함께 객체를 넘기면
어떤 객체에도 속하지 않은 함수가 주어진 객체의 메소드인 것처럼 사용 할 수 있다.const bruce = { name: "Bruce" }; const madeline = { name: "Madeline" }; //이 함수는 어떤 객체에도 속하지 않지만 this를 사용한다. 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이다.
call() 의 첫 번째 매개변수는 this로 사용될 객체이고 나머지 매개변수는 호출한 함수로 넘겨진다.
function update(birthYear, occupation) { this.birthYear = birthYear; this.occupation = occupation; } update.call(bruce, 1949, "singer"); //bruce는 이제 {name: "Bruce", birthYear: 1949, occupation: "singer"} 이다. update.call(madeline, 1942, "actress"); //bruce는 이제 {name: "Madeline", birthYear: 1942, occupation: "actress"} 이다.
apply는 call과 똑같지만 배열을 매개변수로 처리할 때 사용한다.
apply는 매개변수로 배열을 받는다.update.apply(bruce, [1955, "actor"]); //bruce는 이제 {name: "Bruce", birthYear: 1955, occupation: "singer"} 이다. update.apply(madeline, [1918, "writer"]); //madeline는 이제 {name: "Madeline", birthYear: 1918, occupation: "writer"} 이다.
apply를 사용하는 흔한 예제는 배열의 최솟값과 최댓값을 구하는 것이다. 내장함수 Math.min 과 Math.max를 apply를 사용하여 배열을 바로 넘겨줄 수 있다.
const arr = [2, 3, 5, 15, -7]; Math.min.apply(null, arr); //2 Math.max.apply(null, arr); //15
첫 번째 매개변수가 null인 이유는 min 과 max 함수가 this와 관계없이 동작하기 때문이다. 즉, 무엇을 넘기든 상관없다.
확산 연산자(...)를 사용해도 apply와 같은 결과를 얻을 수 있다.
const newBruce = [1942, "pilot"]; update.call(bruce, ...newBruce); //apply(bruce, newBruce) 와 같다. Math.min(...arr); //2 Math.max(...arr); //15
bind는 함수의 동작을 영구적으로 바꾸므로 찾기 어려운 버그의 원인이 될 수 있다고 한다. bind는 매우 유용하지만, 함수의 this가 어디에 묶이는지 정확히 파악하고 사용해야 한다.
bind에 매개변수를 넘기면 항상 그 매개변수를 받으면서 호출되는 새 함수를 만드는 효과가 있다. 예를 들어 bruce가 태어난 해를 항상 1949로 고정하지만, 직업은 자유롭게 바꿀 수 있는 update 함수를 만들고 싶다면 다음과 같이 하면 된다.const updateBruce1949 = update.bind(bruce, 1949); updateBruce1949("singer, songwriter"); //bruce는 이제 {name: "Bruce", birthYear: 1949, occupation: "singer, songwriter"} 이다.
bind는 함수를 특정 객체나 속성으로 고정시키고 사용하는 함수인 것같다.