Javascript 함수의 메소드 call,apply

Posted by negabaro kim on Sunday, March 10, 2019 Tags: javascript   4 minute read

call,apply는 왜 알아야하는가?

this의 참조값을 바꿔서 Javascript의 재사용/공유 패턴을 이해하기 위해

call,apply란

JS function 객체가 기본적으로 갖고 있는 메소드

()와 같은 선언한 함수 호출이 가능

this가 참조하는 값을 바꿀 수 있다.

call,apply의 차이

인자 하나씩 전달하느냐(call) 인자 리스트를 전달하느냐(apply) 의 차이뿐이다

1. 함수호출

함수 뒤에 ()를 붙이는 것과, call 그리고 apply하는 방법이 있다.

call 함수호출 예제

school_meal_clubs.call(null, "다현", "쯔위", "채영");

apply 함수호출 예제

school_meal_clubs.apply(null, ["다현", "쯔위", "채영"]);

2. this참조 값 교체

예제1)

this는 기본적으로 window값을 가지는데 call,apply,bind 를 이용해 이 this값을 바꿔줄 수 있다.

var sana = {
  buzzword: '샤샤샤',
  set_buzzword : function() {
    alert(this.buzzword);
  }
};

var KnowingBros = {
  buzzword: '치즈김밥?'
};

sana.set_buzzword(); // '샤샤샤';
sana.set_buzzword.call(KnowingBros); // '치즈김밥?'

마지막 줄에서 sana.set_buzzword.call(KnowingBros)로 this가 가리키는 것을 sana에서 KnowingBros로 바꾸었다. call,apply를 사용하지 않으면 “샤샤샤”가 출력되지만 사용시 넘겨준 오브젝트안에 선언된 buzzword인 “치즈김밥?”이 출력되었다.

이런식으로 다른객체를 넘겨주므로서 그 객체로 this의 참조값을 변경할 수 있다.

예제2(함수)

function Drop(thing) {
  console.log(this instanceof Sana); // => true //즉 Drop을 호출한 함수(sana)의 this를 가져온것
  this.thing = thing;
}
function Sana(thing, dropCount) {
  console.log(this instanceof Sana); // => true

  Drop.call(this, thing); // 간접 실행
  this.dropCount = dropCount;
}
var sana = new Sana('headband', 2);
console.log(sana); // { name: 'headband', dropCount: 2 }

함수인 경우도 마찬가지다.

Sana함수에서 Drop함수를 call하면서 Sana함수의 this를 첫번째 인자에 넘겨주었다.

Drop함수에서는 instanceof를 통해 자신의 this와 Sana함수를 비교해보니 true가 출력 즉 Sana함수의 this를 넘겨받아 Drop에서 사용가능하게 된것

Sana함수와 Drop함수가 this를 공유하고 있다고 말할 수 있을것 같다.(둘다 Sana함수를 가리키고 있으므로)

예제3 ※2019/8/9일 추가

querySelectorAll과 같이 nodeList형태의 값을 배열처럼 반복시키고 싶을때도 활용이 가능

const twice = document.querySelectorAll('.twice');
[].forEach.call(twice, (m) => {
  console.log(m);
});

twice.foreach.xxx이런식으로는 사용이 불가능하지만 call을 이용해 document.querySelectorAll('.twice');의 결과를 배열처럼 사용이 가능

이것이 가능한 이유는 call의 첫번째 파라메터에 의해서 this가 조작되고(?) 두번째 파라메터에서 조작된 this를 참조해

(m) => {
  console.log(m);
}

를 실행하기 때문

this가 조작되었다는 증거로

2번째 파라메터가 arrow function이 아닌 보통 함수로 바꾸고(arrow에서는 this를 사용못하니깐)

function(m) {
  console.log(twice === this);
}

를 보면 true가 리턴됨

call,apply장점

유용한 메소드들의 재사용/공유가 가능, 중복을 방지

자바스크립트에서 object를 효율적으로 사용하면서 재사용 패턴까지 구현할 수 있는 유용한 방법

https://www.zerocho.com/category/JavaScript/post/57433645a48729787807c3fd
https://www.deep-rain.com/programming/javascript/919