함수 호출 call, apply, bind의 차이

조성철 (JoSworkS)·2020년 3월 7일
8

TIL(Today I Learned)

목록 보기
31/73
post-thumbnail

함수 호출과 관련하여 지금까지 자주 쓰이지는 않았지만, 반드시 알아야 할 개념이 있다. 바로 call / apply / bind을 이용한 함수 호출 방법이다.

함수 호출

자바스크립트에서 함수를 호출하는 방법에는 먼저, 가장 일반적이고 빈번히 사용되는 함수 뒤에 ()를 붙여 호출하는 방법과 call, apply를 사용하여 호출하는 방법이 있다.

아래 예제 코드를 보면 각기 함수 호출 방식은 다르지만, 같은 결과를 보여주고 있다.

그러면 각 호출 방법에 매개변수는 어떤 역할을 하는지 차이점을 무엇인지에 대해 조금 더 자세히 알아보도록 하겠다.

function foo(a, b, c) {
  console.log(a + b + c);
};
foo(1, 2, 3); // 6
foo.call(null, 1, 2, 3); // 6
foo.apply(null, [1, 2, 3]); // 6

1. Function.prototype.call()

먼저 MDN의 기재되어 있는 call()의 매개변수의 설명을 보면 아래와 같다.

func.call(thisArg[, arg1[, arg2[, ...]]])

  • thisArg: func 호출에 제공되는 this의 값
  • arg1, arg2, ...: func이 호출되어야 하는 인수

첫 번째 매개변수 thisArg는 각 함수의 실행문맥의 this를 특정하게 지정하는 매개변수임을 알 수 있다. 그리고 두 번째부터는 호출할 함수의 인수들이 들어간다.

아래 예제 코드를 보면 call을 이용하여 person2의 함수를 호출하고 있지만 call 메소드 첫 번째 매개변수에 person1을 넣어주고 있기 때문에 this는 person2가 아닌 person1을 가리키게 된다.

let person1 = {
    name: 'Jo'
};

let person2 = {
    name: 'Kim',
    study: function() {
        console.log(this.name + '이/가 공부를 하고 있습니다.');
    }
};

person2.study(); // Kim이/가 공부를 하고 있습니다.

// call()
person2.study.call(person1); // Jo이/가 공부를 하고 있습니다.

2. Function.prototype.apply()

fun.apply(thisArg, [argsArray])

  • thisArg: func 호출에 제공되는 this의 값
  • argsArray: func이 호출되어야 하는 인수를 지정하는 유사 배열 객체

첫 번째 매개변수 thisArg는 Function.prototype.call()과 같이 this를 지정한다. 하지만 call()과 다르게 apply()는 두 번째 매개변수를 배열 형태로 넣게된다는 차이점이 있다.(배열 또는 유사배열 객체)

예제 코드는 call()과 같이 때문에 생략하도록 하겠다. 위에서 언급하였지만, 단지 두 번째 매개변수를 배열 형태로 넣어준다.

3. Function.prototype.bind()

func.bind(thisArg[, arg1[, arg2[, ...]]])

  • thisArg: 바인딩 함수가 타겟 함수의 this에 전달하는 값
  • arg1, arg2, ...: func이 호출되어야 하는 인수

bind()는 새롭게 바인딩한 함수를 만든다. 바인딩한 함수는 원본 함수 객체를 감싸는 함수이다. bind()는 call(), apply()와 같이 함수가 가리키고 있는 this를 바꾸지만 호출되지는 않는다. 따라서 변수를 할당하여 호출하는 형태로 사용된다.

let person1 = {
    name: 'Jo'
};

let person2 = {
    name: 'Kim',
    study: function() {
        console.log(this.name + '이/가 공부를 하고 있습니다.');
    }
};

person2.study(); // Kim이/가 공부를 하고 있습니다.

// bind()
let student = person2.study.bind(person1);

student(); // Jo이/가 공부를 하고 있습니다.

추가 내용

arguments 객체는 함수에 전달된 인수에 해당하는 Array 형태의 객체

function foo(a, b, c) {
  console.log(arguments);
}

foo(1, 2, 3); // Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]

call(), apply()는 함수의 유사배열인 arguments 객체를 활용할 수 있도록 해준다. 유사배열은 보통의 배열과 형태는 같지만, 배열이 아니기 때문에 Array.prototype.join() 등의 배열의 메소드를 사용할 수 없다.

function foo(a, b, c) {
  console.log(arguments.join());
}

foo(1, 2, 3); // Uncaught TypeError: arguments.join is not a function

하지만 call(), apply()를 이용하면 arguments 객체에 배열 메소드를 사용하는 것이 가능하다.

function foo(a, b, c) {
  console.log(Array.prototype.join.call(arguments));
}

foo(1, 2, 3); // 1,2,3

참고 자료

0개의 댓글