프론트엔드 개발/JavaScript

JavaScript - call, apply, bind

하이고니 2023. 1. 31. 17:19
 

https://www.zerocho.com/category/JavaScript/post/57433645a48729787807c3fd

 

www.zerocho.com

위 블로그를 필사하면서 공부한 내용입니다.

 

함수는 원래 선언한 후 호출해야 실행된다.

호출하는 방법으로는 함수 뒤에 ()를 붙이는 것과 call, apply 하는 방법이 있다.

const example = function (a, b, c) {
  return a + b + c;
};
example(1, 2, 3);
example.call(null, 1, 2, 3);
example.apply(null, [1, 2, 3]);

call은 보통 함수와 똑같이 인자를 넣고, apply는 인자를 하나로 묶은 배열의 형태로 넣는다.

null의 역할은 무엇일까?

 

this를 대체하는 것.

 

const obj = {
  string: 'hajongon',
  yell: function() {
    alert(this.string);
  }
};
const obj2 = {
  string: 'what?'
};

obj.yell(); // 'hajongon';
obj.yell.call(obj2); // 'what?'

 

마지막 줄에서 obj.yell.call(obj2) 를 통해 this가 가리키는 것을 obj에서 obj2로 바꿨다.

yell은 obj의 메소드인데도 zero 대신에 what?이 alert 되었다. 즉 다른 객체의 함수를 자기 것처럼 사용할 수 있다는 것.

 

call, apply, bind 는 arguments를 조작할 때 사용된다.

arguments는 함수라면 처음부터 갖고 있는 숨겨진 속성이다. 함수에 들어온 인자를 배열 형식(배열은 아님. 유사 배열)으로 반환한다.

 

function example() {
  console.log(arguments);
}
example(1, 'string', true); // [1, 'string', true]

 

생긴 건 배열이지만, 배열이 아닌 유사 배열이기 때문에 배열의 메소드는 쓸 수 없다.

 

function example2() {
  console.log(arguments.join());
}
example2(1, 'string', true); // Uncaught TypeError: arguments.join is not a function

 

이렇게 에러가 발생하는데, 이를 call이나 apply로 해결할 수 있다.

 

function example3() {
  console.log(Array.prototype.join.call(arguments));
}
example3(1, 'string', true); // '1,string,true'

 

배열의 프로토타입에 있는 join 함수를 빌려쓰는 개념이다. 여기서 this는 arguments를 가리킨다.

join 외에도 slice, concat 등 모든 메소드를 이 방식으로 사용할 수 있다.

 

bind 함수는 함수가 가리키는 this만 바꾸고 호출하지는 않는다.

 

const obj = {
  string: 'hajongon',
  yell: function() {
    alert(this.string);
  }
};
const obj2 = {
  string: 'what?'
};

const yell2 = obj.yell.bind(obj2);
yell2(); // 'what?'

 

obj.yell.bind(obj2) 하면 yell 함수의 this가 obj2로 바뀐다. 즉 call이나 apply와 비슷하지만 호출은 하지 않고 함수만 반환하는 것이다. call(this, 1, 2, 3)bind(this)(1, 2, 3) 과 같다.