add(x,y) {
this.val = x + y;
console.log(this.val);
}
let obj = { val: 0 };
add.apply(obj, [2, 8]); // .apply(thisArg, [argsArray])
add.call(obj, 2, 8); // .call(thisArg[, arg1[, arg2[, ...]]]);
let arr = [12, 234, 5, 42, 12];
Math.max(12,234,5,42,12); // 234
Math.max(arr); // NaN
//Math.max는 인자들을 쉼표로 구분하여 넘겨줘야하기 때문에 배열을 넘겨줄 수 없다.
// apply() 함수 사용
Math.max.apply(null, arr) // 234
// apply함수를 적용해줄 대상이 따로 없을 때는 첫번째 매개변수는 의미가 없기 때문에 null을 넣어줌
function moreThanFive(str) {
return str.length > 5;
}
let arr = ['code', 'states'];
arr에 있는 문자열 배열의 요소들에 filter메소드를 사용해서 moreThanFive함수를 적용한 요소들만 반환할 수 있다.
arr.filter(moreThanFive); // ['states']
하지만 filter라는 메소드는 Array.prototype에 포함되어 있는 메소드이기 때문에 call(), apply()를 사용해 가져와서 사용할 수 있다.
Array.prototype.filter.call(arr, moreThanFive) // ['states']
Array.prototype.filter.apply(arr, [moreThanFive]) // ['states']
이런 패턴은 언제 사용하는 걸까?
자바스크립트에는 배열처럼 생겼지만 배열이 아닌 유사배열이라는 것이 있다. 아래 사진은 Google 메인 페이지에서 document.querySelectorAll('a')를 실행한 결과이다. 결과를 보면 배열처럼 값들이 나열되어있는 것이 보이는데 이런것이 대표적인 유사배열이다.
유사배열에는 배열처럼 배열의 메소드들을 사용할 수가 없는데 이런 경우 앞서 봤던 apply와 call을 사용해서 배열의 메소드를 빌려와서 사용할 수 있다.
call/apply와는 다르게, 함수를 바로 실행시키지 않고, this값이 바인딩된 함수를 리턴
function add(x, y) {
this.val = x + y;
consol.log(this.val);
}
let obj = { val: 0 };
let boundFn = add.bind(obj, 2, 8); // boundFn은 함수
boundFn() // 10, add는 여기서 실행
function Box(w, h) {
this.width = w;
this.height = h;
this.getArea = function() {
return this.width * this.height;
}
this.printArea = function() {
console.log(this.getArea());
}
}
let box1 = new Box(100, 50);
box1.printArea() // 5000
setTimeout(box1.printArea, 4000)
위의 코드와 같은 상황에서 setTimeout(box1.printArea, 4000)를 실행했을 때 4초 후에 box1.printArea()가 실행될 꺼라고 생각할 수 있는데 그렇지 않다.