[자바스크립트] call과 apply

yeong·2022년 5월 9일
0

javascript

목록 보기
3/5

메소드를 사용하다보면 가끔 ReferenceError가 뜨며 참조할 수 없다고 나올때가 있다.
경험상 90%가 인수를 제대로 넘기지 않았거나 this를 잃어버린 상황이다.
객체 내 메소드를 사용할때 this를 제대로 바인딩시키는게 매우 중요하다.
메소드 내 this가 제대로된 참조값을 갖도록하기 위해 call, apply, bind 를 사용할 수 있다.

call

call
설명 : this를 명시적으로 고정해 함수를 호출할 수 있게 해주는 내장메소드.
ex: function.call(context,[arg1,arg2...])

call에 첫번째인수로 객체를 명시해주면 호출되는 메서드의 this가 명시된 객체로 고정된다.
call에 나머지 인수들은 호출되는 메서드의 매개변수로 넘어간다.

예를들어

const student={
	name:"John",
	age:16,
	addr:"seoul",
   	introduce (greetings ){
     return greetings + "my name is " + this.name;
    }
}

student 라는 객체가 있으며 위와같은 속성들을 가졌다고 하자.
만약 student.introduce("hello")를 호출한다면 의도대로 동작하지만, student.introduce를 임시변수 say 복사한뒤 say("hello")를 호출한다면 오류가 발생하거나 의도하지 않은 방향(undefined 참조)으로 작동할 수 있다.
introduce 메서드 내 this.name에서 this 가 undefined를 가리키기 때문이다.
이러한 상황을 해결하기 위해서 call을 사용할 수 있다.

let saySomething ;
const say = student.introduce;
saySomething = say("hello!!");
console.log(saySomething); //hello!!my name is undefined

saySomething = say.call(student, "bye!");
console.log(saySomething); //bye!my name is John

call은 위와같이context를 지정하여 this가 바인딩되도록 할때 유용하다.

apply

apply
설명 : this를 명시적으로 고정해 함수를 호출할 수 있게 해주는 내장메소드.
ex: function.call(context,[args])

apply는 this를 바인딩시켜주는 역할을 한다는점에서는 비슷하지만 유사배열객체를 인수로 넘길 수 있다는점에서 차이가 있다.

call을 사용해 1개이상의 인수를 넘길때는 각 인수를 나열해주어야하며, 만약 배열을 인수로 넘기기위해서는 spread문법을 이용해 인수로 넘겨야한다.
반면 apply을 사용하여 복수의 인수를 넘길때 인수가 담긴 배열을 통째로 넘기면 순서에 따라 매개변수가 매핑된다.

예시를 들어 비교하면 아래와 같다.

const student = {
  name: "John",
  age: 16,
  addr: "seoul",
  introduce(a, b) {
    return `${a} ${b}  ${this.name}`;
  },
};
student.introduce("hello...");

const say = student.introduce;

const saySomething = say.call(student, "bye!", "hello");
const saySomething2 = say.apply(student, ["bye!", "hello"]);
console.log(saySomething); //bye!my name is John
console.log(saySomething2); //bye!my name is John


인수가 넘어가는 형태를 제외하고 두 메서드는 동일하지만 자바스크립트 엔진내부에서 apply를 최적화하기 때문에 apply를 사용하는 것이 조금 더 빠르다.

실제로 일부 내장함수에 대해서는 apply를 이용하면 배열과 루프없이 쉽게 처리할 수 있다고 한다. 예를들어 Math.max(...args)를 구하기 위해 Math.max.apply([args])를 사용하는것이 더 효율적일 수 있다.

profile
안녕하세요!

0개의 댓글