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이 프로토타입인 것을 확인할 수 있다.