이번 포스트에는 함수의 method 인 .call과 .apply 그리고 .bind까지 복습해볼 것이다.
일단 지난번에 복습했듯 .call과 .apply의 차이는 인자를 하나 하나씩 받는 것, 그리고 인자를 배열로 받는 것 그 차이가 있다.
call 과 apply 의 예제를 보자.
function add (x, y){
this.val = x+y;
console.log(this.val)
}
let obj = {val: 0};
add.call(obj, 2, 8); //10
add.apply(obj, [2, 8]); //10
call 과 apply 모두 함수를 실행하지만 인자로 들어가는 것이 다르다.
let arr = [1, 4, 2, 8, 3];
Math.max.apply(null, arr); //8
apply에서 만약에 배열만 받는다면 this 값이 의미가 없을 때는 null을 넣어주면 된다.
.bind는 call 혹은 apply처럼 함수를 실행하지 않고 this 값이 바인딩된 함수를 리턴한다.
let bindit = add.bind(obj, 2, 8);
bindit 을 하면 add함수가 obj라는 this값을 바인딩 해서 함수를 호출한다. 클로저 처럼 호출을 하고 실행은 하지 않는다. 그래서 bindit()을 하면 10이라는 값을 준다. bind는 보통 this의 값을 무엇으로 고정시켜 바인드 하고 싶을 때 사용한다.
function whatisprice (allowance, cost){
this.cost = cost;
this.allowance = allowance;
this.getchange = function () {
return this.allowance - this.cost;
}
this.printchange = function () {
console.log(this.getchange() )
}
};
let water = new whatisprice(50, 20);
water.printchange() //30;
이렇게 예를 들어서 코드를 짜보면 여기서 this 는 whatisprice 라는 class의 instance 인 water이다.
그렇다면 바인딩은 언제 쓰는 것일까?
setTimeout(water.printchange, 5000);
이 코드를 실행한다면 30이 5초 후에 나올 수 있을까? 답은 아니다 이다.
setTimeout이 실행되면 this의 값이 기본적으로 window 객체가 된다. 그러므로 water가 this가 아니기 때문에 없는 함수라고 나온다. 이걸 해결할 때 bind를 이용해 this의 값을 water로 설정해주는 것이다.
setTimeout(water.printchange.bind(water), 5000);
이런 식으로 this의 값을 water로 지정해준다면 문제없이 코드가 돌아간다.
bind로는 커링도 가능하다.
function greeting (name, age) {
return "Hi, my name is " + name + " and I am " + age;
}
let Joshua = greeting.bind(null, "Joshua");
여기서 Joshua는 greeting이라는 함수 자체를 반환한다. 하지만 그 속에는 "Joshua"가 바인드 돼있다. this의 값을 지정해주지 않기 때문에 bind의 첫번 째 인자는 null이다.
Joshua(18); // "Hi, my name is Joshua and I am 18"을 반환한다.
기억하자! bind는 this의 값을 지정해주기 위해 사용한다는 것.