call과 apply 메서드를 이용한 명시적인 this 바인딩
apply()
와 call()
메서드를 이용하면 명시적으로 this
를 원하는 객체에 바인딩할 수 있다.
function.apply(thisArg, argArray)
첫번째 인자 thisArg는 apply()
메서드를 호출한 함수 내부에서 사용한 this
에 바인딩할 객체를 가리킨다. 즉, 첫번째 인자로 넘긴 객체가 this
로 명시적으로 바인딩 되는 것이다. 두번째 argArray 인자는 함수를 호출할 때 넘길 인자들의 배열을 가리킨다.
apply()
나 call()
메서드는 this
를 원하는 값으로 명시적으로 매핑해서 특정 함수나 메서드를 호출할 수 있다는 장점이 있다. 이들 대표적인 용도가 arguments
객체와 같은 유사 배열 객체에서 표준 배열 메서드를 사용하는 것이다.
function myFunction(){
console.dir(arguments);
//arguments.shift(); 에러 발생
//arguments 객체를 배열로 변환
var args = Array.prototype.slice.apply(arguments);
console.dir(args);
}
myFunction(1,2,3);
위 예제는 arguments
객체가 Array.prototyp.slice()
메서드를 마치 자신의 메서드인것 처럼 arguments.slice()와 같은 형태로 메서드를 호출하라는 것이다.
slice()
메서드는 인자 없이 호출할 경우, 이 메서드를 호출한 배열(여기서는 arguments 객체)을 복사한 새로운 배열을 생성한다. 따라서 arguments
객체의 모든 요소를 그대로 복사한 배열이 생성되고, 이것은 args 변수에 리턴된다.
아래는 실행 결과이다.
Arguments[3]
0: 1
1: 2
2: 3
callee: myFunction()
length: 3
__proto__: Object
Array[3]
0: 1
1: 2
2: 3
length: 3
__proto__: Array[0]
arguments와 args 모두 같은 프로퍼티가 있는 것 처럼 보이지만 두 객체의 __proto__
프로퍼티는 다르다. arguments는 객체이므로 프로토타입이 Object.prototype
인 반면에 args는 배열이므로 Array.prototype
이 프로토타입인 것을 확인할 수 있다.