어제의 나보다 성장한 오늘의 나

[자바스크립트] call과 apply 본문

공부/JavaScript && jquery

[자바스크립트] call과 apply

NineOne 2021. 4. 16. 00:25

자바스크립트에서 함수 호출이 발생할 때 각각의 상황에 따라 this가 정해진 객체에 자동으로 바인딩된다.

이러한 내부적인 this 바인딩 이외에도 this를 특정 객체에 명시적으로 바인딩시키는 방법도 제공한다.

apply()와 call() 메서드는 모든 함수의 부모 객체인 Function.prototype 객체의 메서드이므로, 다음과 같은 형식으로 호출하는 것이 가능하다.

function.apply(thisArg, argArray)
  • 둘의 기능은 같고 넘겨받는 인자의 형식만 다르다.
  • apply : 호출하는 주체가 함수, this를 특정 객체에 바인딩할 뿐 본질적인 기능은 함수 호출이다.

그럼 더욱 apply에 자세히 살펴보자

  1. 첫 번째 인자 thisArg는 apply() 메서드를 호출한 함수 내부에서 사용한 this에 바인딩할 객체를 가리킨다. 
    즉! 첫 번째 인자로 넘긴 객체가 this로 명시적으로 바인딩된다.
  2. 두 번째 argArray 인자는 함수를 호출할 때 넘길 인자들을 배열을 가리킨다. 
	// 생성자 함수
        function Person(name,age,gender){
            this.name=name;
            this.age=age;
            this.gender=gender;
        };
        
        // foo 빈 객체 생성
        var foo = {};
        
        // apply() 메서드 호출
        // 1. 첫번째 인자: foo
        // -> Person() 함수에서 this로 바인딩된다.
        // 2. 두번째 인자
        // -> 호출하려는 Person() 함수의 인자 name,age,gender로 각각 전달된다.
        
        // 결론
        // -> Person('foo',30,'man') 함수를 호출하면서 this를 foo객체에 명시적으로 바인딩하는 것을 의미
        Person.apply(foo,['foo',30,'man']);
        
        console.log(foo);

위에서 말한 call() 메서드는 apply와 기능이 같다고 했다. 그러면 어떤 형태로 불리는지 보자!

Person.call(foo, 'foo',30,'mam');

 

  • 위의 코드를 call() 메서드로 바꾼 예제이다.
  • 두 번째 인자에서 배열 형태로 넘긴 것을 각각 하나의 인자로 넘기게 된다.
  • apply()나 call() 메서드는 this를 원하는 값으로 명시적으로 매핑해서 특정 함수나 메서드를 호출할 수 있다는 장점이 있다. 그리고 이들의 대표적인 용도가 바로! arguments객체와 같은 유사 배열 객체에서 배열 메서드를 사용하는 경우이다.

 

arguments 객체는 실제 배열이 아니다! 그래서 pop(), shift() 같은 표준 배열 메서드를 사용할 수 없다! 하지만 apply() 메서드를 이용하면 가능하다!

       function myFunction(){
            console.log(arguments);
            arguments.shift(); // 에러발생
            
            // arguments 객체를 배열로 변환
            var args = Array.prototype.slice.apply(arguments);
        }
        
        myFunction(1,2,3);
  • arguments 객체는 length 프로퍼티만을 가진 유사 객체 배열이다. 그래서 표준 메서드를 호출하면 에러가 발생한다
  • 위 코드를 해석하면 다음과 같다 'Array,prototype.slice() 메서드를 호출해라. 이때 this는 arguments 객체로 바인딩해라'이다.

  • 결과를 살펴보면 arguments와 args 모두 같은 프로퍼티가 있는 것처럼 보이지만 두 객체의 __proto__프로퍼티는 다르다.
  • arguments는 객체이므로 프로토 타입이 Object.prototype
  • args는 배열 Array.prototype

 

출처

인사이드 자바스크립트(송형주, 고현준 지음) - 한빛미디어

Comments