Studying/JavaScript & Frameworks

[자바스크립트 떠먹여 주는 남자] Call, Apply, 그리고 Bind (1)

국장 지킴이 앨런 2022. 3. 22. 09:00
반응형

안녕하세요. 오늘은 제가 면접 인터뷰에서 받은 질문 중 하나인 Call, Apply, 그리고 Bind 에 대하여 알아보도록 하겠습니다. 창피하게도 개발 경력 만 3년에 가까움에도 불구하고, 인터뷰 질문을 받았을 때 적지 아니 당황했었습니다. 한번도 들어본 적이 없었기 때문이죠.. 물론 쓸 일이 없어서 그랬다고는 하지만, 면접관의 입장에서는 '경력직 JS 개발자라면 이 정도는 알아야 하지 않나' 라는 예상을 한다고 생각해 볼 수가 있겠죠. 그래서 최근 제 공부 목표는 '내실을 다지자' 입니다. 아직도 배워야 할 것들이 너무나 많지만, 이렇게 하나 하나씩 공부하다 보면 언젠간 당당하게 기술 면접을 통과할 수 있지 않을까 싶네요. 그럼 본격적으로 저것들이 뭔지 한번 찍먹 해보도록 하겠습니다.

 

JavaScript Function call()

call() 메소드는 사전 정의 된 자바스크립트 메소드 입니다. 코드 예제를 보면서 설명 드리도록 하겠습니다.

// Code from https://www.w3schools.com/js/js_function_call.asp
const person = {
  fullName: function() {
    return `${this.firstName} ${this.lastName}`;
  }
};

const person1 = {
  firstName: "John",
  lastName: "Doe"
};

const person2 = {
  firstName: "Jane",
  lastName: "Doe"
};

console.log(person.fullName.call(person1));

위의 코드에서 저는 person 이란 객체를 선언하였고, 그 객체 안에 fullName 이란 프로퍼티를 선언하였는데, 그 값은 일반 값이 아닌 펑션의 리턴값입니다. 그리고 그 아래 John DoeJane Doe 라는 사람읍 객체를 선언하였구요. 마지막으로 fullName 프로퍼티를 호출하는데, call() 메소드를 이용하여 fullName 호출 시 John Doe 의 이름이 리턴 되게끔 하였습니다. 아래의 이미지는 제가 위의 코드를 실행시켰을 때의 결과값입니다.

person1 argument 를 이용하여 call() 메소드 호출 시 결과값

말씀 드렸다시피 John Doe 가 결과값으로 출력 되었습니다. 참 쉽죠?

하지만! 주의할 점을 한가지 말씀 드리겠습니다. 이 글을 보시는 분들 대부분 모두 알고 계실 듯 하지만, call 메소드 호출 시, 인자 (argument) 안의 프로퍼티 이름이 똑같지 않다면 undefined 가 리턴됩니다.


위의 코드 예제에서 fullName 의 펑션 안에는 매개변수가 아무것도 선언되어있지 않았습니다. 하지만, 우리는 따로 매개변수를 추가할 수도 있는데요, 역시 코드 예제로 확인해 보겠습니다.

// Code from https://www.w3schools.com/js/js_function_call.asp
const person = {
  fullName: function(city, country) {
  	return `${this.firstName} ${this.lastName} lives in ${city}, ${country}`;
  }
};

const person1 = {
  firstName: "John",
  lastName: "Doe"
};

console.log(person.fullName.call(person1, "New York", "The United States"));

위 코드 예제의 실행 결과값은 이렇습니다.

이렇듯 call 메소드를 사용하여 다양한 객체에 사용 가능한 메소드를 만들 수 있습니다 (메소드 재사용).

JavaScript Function apply()

자바스크립트의 apply() 메소드는 call() 메소드와 매우 비슷합니다. 역시 예제를 통해서 보도록 하겠습니다.

// Code from https://www.w3schools.com/js/js_function_apply.asp
const person = {
  fullName: function() {
    return `${this.firstName} ${this.lastName}`;
  }
}

const person1 = {
  firstName: "Mary",
  lastName: "Doe"
}

console.log(person.fullName.apply(person1));

위의 코드는 call() 메소드를 사용했을 때처럼 person1 안의 firstName 과 lastName 프로퍼티 밸류 값을 리턴할 것입니다. 여기까지만 봤을 때는 call() 과 전혀 다른 점이 없죠.

하지만 아래의 코드를 보시면 다른 점을 찾을 수 있습니다.

// Code from https://www.w3schools.com/js/js_function_apply.asp
const person = {
  fullName: function(city, country) {
    return `${this.firstName} ${this.lastName} lives in ${city}, ${country}`;
  }
}

const person1 = {
  firstName:"John",
  lastName: "Doe"
}

console.log(person.fullName.apply(person1, ["Oslo", "Norway"]));

call() 메소드의 코드를 보시면, fullName 에 보내는 인자들 (arguments) 이 독립적인 것을 볼 수 있습니다. 하지만, apply() 메소드의 경우, fullName 안의 매개변수들은 독립적이지만, 호출 시키는 곳에서의 인자의 배열 (array) 의 형태임을 볼 수 있습니다. 이 점이 call 과 apply 메소드의 차이점입니다.

JavaScript Function bind()

bind() 메소드를 통해서, 객체는 다른 객체로부터 메소드를 빌려 사용할 수 있습니다. 무슨 말인지 아직 잘 모르겠으니 코드 예제를 통해 확인 해 보도록 하겠습니다.

// Code from https://www.w3schools.com/js/js_function_bind.asp
const person = {
  firstName: "John",
  lastName: "Doe",
  fullName: function() {
    return `${this.firstName} ${this.lastName}`;
  }
};

const member = {
  firstName: "Hege",
  lastName: "Nilsen"
};

const membeFullName = person.fullName.bind(member);
console.log(membeFullName());

위의 코드에서, person 객체는 firstName 과 lastName 의 값을 리턴하는 fullName 이라는 프로퍼티를 가지고 있지만, member 객체는 firstName 과 lastName 만을 가지고 있습니다. 따라서 bind() 메소드를 통해 member 객체는 person 객체로부터 fullName 메소드를 빌려올 수 있습니다. 호출 방법은:

  1. 새로운 변수를 선언하고
  2. const boundMethod = sourceObject.methodName.bind(targetObject); 형식으로 코드를 써줍니다. 여기서 sourceObject 는 우리가 메소드를 빌려 올 객체이고 targetObject 는 메소드를 빌려 쓸 객체를 의미합니다.
  3. 메소드를 빌려 왔기 때문에 호출하기 위해서는 boundMethod(); 처럼 괄호를 넣어 주어야 합니다.

아래 이미지는 위의 코드를 실행하였을 때 나오는 결과값입니다.

bind() 실행 결과

이번 포스트에서는 call, apply, bind 메소드에 관하여 살짝 찍먹 해 보았습니다. 한 포스트에 모든 내용을 다 담아야 하나 생각해 보았지만, 제 머리가 그걸 허용하지 않아 오늘은 기본 개념과 호출 방법에 대해서만 정리를 해 보았습니다. 그리하여 다음번 포스트에서는, 이번 포스트에서 담지 못한 조금 더 어려운 내용들을 다뤄보려고 합니다. 저도 몰랐던 부분이기에 정리할 시간이 조금 더 필요할 것 같아 내린 결정이니 양해 부탁 드리겠습니다 .
그럼 더욱 잘 정돈 된 포스트로 다시 찾아 뵙도록 하겠습니다.
 
반응형