call, apply, bind

minho·2021년 10월 13일
0

원래 함수는 선언한후 호출해야 한다.
호출방법으로는 함수뒤에 ()를 붙이거나 call, apply를 붙이는 방법이 있다.

call과 apply

var 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]);

여기 예시가 있다. 위의 값은 모두 6이다.
call과 apply에서 공통적으로 들어가는 null은 무엇인가?

func.call(thisArg[, arg1[, arg2[, ...]]])
fun.apply(thisArg, [argsArray])

바로 this를 대체하는 것이다.
그렇다면 다른예시를 살펴보자.

var obj = {
  string: 'zero',
  yell: function() {
    alert(this.string);
  }
};
var obj2 = {
  string: 'what?'
};
obj.yell(); // 'zero';
obj.yell.call(obj2); // 'what?'

yell에서 this는 변수 obj를 가리키므로 zero를 출력하는 것은 당연하다.
그러나 yell의 this를 obj2로 바꿀수 있다!?!?!
이처럼 call을 이용하면 this가 향하는 곳을 바꿀 수 있다.
즉, 다른 객체의 함수를 자기 것마냥 사용할 수 있다.

이를 이용하면 함수의 argument를 조작할 수 있다.

argument란?

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'

여기서 Array.prototyle은 배열로 만드는 것을 말한다.
즉, call을 이용해 this를 argument(1, 'string', true)로 바꾸게 한 후 이것을 배열로 만든다. 그후 join메소드를 이용해 합치게 한다. // 결과: '1,string,true'

여담

Array.prototype.join.call(arguments)과 Array.prototype.join.call(arguments, " ")

Array.prototype.join.call(arguments, " ")의 괄호에서 첫번째 인수는 this의 인수이고, 두번째 인수는 join의 인수이다.
잘못된 예: Array.prototype.join('').call(arguments)

bind

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

예를들어 설명해보자

let user = {
  firstName: "John"
};

function func() {
  alert(this.firstName);
}

let funcUser = func.bind(user);
funcUser(); // John

funcUser 는 func에 user를 bind했다.
즉, func의 this는 user를 가리킨다.
결과적으로 user.firstName을 출력하므로 "John"이 출력된다.

profile
Live the way you think

0개의 댓글