[JS 개념정리 2] call, apply, bind 메서드

2024. 6. 30. 21:13·Programming/FE

call, apply, bind 메서드는 JavaScript에서 함수의 this 값을 명시적으로 지정하고 함수를 호출하는 방법을 제공한다. Function.prototype의 메서드이므로 모든 (화살표함수를 제외한)함수에서 사용할 수 있다. 

 

call 메서드

  • syntax: func.call(thisArg, arg1, arg2, ...)

주어진 this 값과 개별적으로 제공되는 인수들로 함수를 호출

function greet(greeting) {
    console.log(`${greeting}, ${this.name}`);
}

const person = { name: "Alice" };
greet.call(person, "Hello"); // 출력: Hello, Alice

 

apply 메서드

  • syntax: func.apply(thisArg, [argsArray])

주어진 this 값과 배열(또는 유사 배열 객체)로 제공되는 인수들로 함수를 호출

function introduce(greeting, profession) {
    console.log(`${greeting}, I'm ${this.name} and I'm a ${profession}.`);
}

const person = { name: "Bob" };
introduce.apply(person, ["Hi", "developer"]); // 출력: Hi, I'm Bob and I'm a developer.

 

bind 메서드

  • syntax: func.bind(thisArg[, arg1[, arg2[, ...]]])

새로운 함수를 생성.

생성된 함수의 this는 bind의 첫 번째 인수로 고정되며, 이어지는 인수들은 원본 함수의 인수 앞에 덧붙여진다.

function multiply(a, b) {
    return a * b * this.factor;
}

const doubler = { factor: 2 };
const doubleMult = multiply.bind(doubler);

console.log(doubleMult(3, 4)); // 출력: 24 (3 * 4 * 2)

// 부분 적용(partial application)도 가능합니다
const tripler = { factor: 3 };
const triple6 = multiply.bind(tripler, 6);
console.log(triple6(7)); // 출력: 126 (6 * 7 * 3)

 

함수를 즉시 실행하는 call과 apply와 달리 bind는 새 함수를 반환한다.

bind를 사용하면 부분 적용을 통해 함수의 인수를 미리 설정할 수 있다(partial application).

 

bind 메서드를 이용한 partial application의 예

function multiply(x, y, z) {
    return x * y * z;
}

// x를 2로 고정
const doubleMultiply = multiply.bind(null, 2);
console.log(doubleMultiply(3, 4)); // 출력: 24 (2 * 3 * 4)

// x를 2로, y를 3으로 고정
const sixTimes = multiply.bind(null, 2, 3);
console.log(sixTimes(4)); // 출력: 24 (2 * 3 * 4)

 

const user = {
    name: 'Alice',
    greet: function(greeting, punctuation) {
        console.log(`${greeting}, ${this.name}${punctuation}`);
    }
};

// 'Hello'로 인사말 고정, this를 user 객체로 바인딩
const greetHello = user.greet.bind(user, 'Hello');

greetHello('!'); // 출력: Hello, Alice!
greetHello('.'); // 출력: Hello, Alice.

// 'Hi'와 '!'로 고정
const greetHi = user.greet.bind(user, 'Hi', '!');
greetHi(); // 출력: Hi, Alice!

 

function createElement(type, className, text) {
    const el = document.createElement(type);
    el.className = className;
    el.textContent = text;
    return el;
}

// div 엘리먼트 생성 함수
const createDiv = createElement.bind(null, 'div');

const redDiv = createDiv('red', 'This is a red div');
const blueDiv = createDiv('blue', 'This is a blue div');

// 버튼 생성 함수
const createButton = createElement.bind(null, 'button', 'btn');

const submitButton = createButton('Submit');
const cancelButton = createButton('Cancel');

 

이러한 방식으로 bind를 사용하면 기존 함수를 기반으로 새로운 특화된 함수를 쉽게 만들 수 있다. 코드의 재사용성을 높여 반복을 줄여 더 명확한 코드 작성에 활용이 가능하다.

 

 

사용하는 경우

 

  • 특정 객체의 컨텍스트에서 함수를 실행해야 할 때
  • 콜백 함수의 this 값을 제어해야 할 때
  • 함수 빌려쓰기 패턴(Function barrowing)을 구현할 때
  • 부분 적용을 통해 함수를 커스터마이즈할 때

 

함수 빌려쓰기 패턴(Function borrowing)

Javascript에서 한 객체의 메서드를 다른 객체에서 사용하는 기법이다. 한 객체의 메서드를 다른 객체의 컨텍스트에서 실행해 코드의 재사용성을 높일 수 있다.

 

사용예

배열 메서드 빌려쓰기

const arrayLike = {0: 'a', 1: 'b', 2: 'c', length: 3};
const realArray = Array.prototype.slice.call(arrayLike);
console.log(realArray); // ['a', 'b', 'c']

 

객체 간 메서드 공유

const person = {
  fullName: function(city, country) {
    return `${this.firstName} ${this.lastName}, ${city}, ${country}`;
  }
};

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

console.log(person.fullName.call(john, "New York", "USA"));
// John Doe, New York, USA

 

 

유사 배열 객체에 배열 메서드 사용하기(arguments 등)

function sum() {
  return Array.prototype.reduce.call(arguments, (acc, curr) => acc + curr, 0);
}

console.log(sum(1, 2, 3, 4)); // 10

 

  • ES6+ 환경에서는 spread 연산자나 Array.from() 같은 대안이 있어 함수 빌려쓰기를 사용하지 않아도 됨

 

메서드 체이닝

const formatter = {
  format: function(str) {
    return str.toUpperCase();
  }
};

const printer = {
  print: function(str) {
    console.log(str);
  }
};

const formatAndPrint = function(str) {
  const formatted = formatter.format.call(this, str);
  printer.print.call(this, formatted);
};

formatAndPrint("hello"); // HELLO

 

함수 빌려쓰기 패턴은 Javascirpt의 유연성을 활용할 수 있는 방법이다. 하지만 다음과 같이, 더 직관적인 최신 Javascript 기능을 활용할 수 있다면 그를 사용하는 것이 좋다. 

 

// 유사 배열을 배열로 변환
const arrayLike = {0: 'a', 1: 'b', 2: 'c', length: 3};
const realArray = Array.from(arrayLike);

// 배열에서 최대값 찾기
const numbers = [5, 6, 2, 3, 7];
const max = Math.max(...numbers);

 

 

'Programming > FE' 카테고리의 다른 글

[JS 개념정리 3] scope, 스코프 체인, 호이스팅, TDZ, 클로저  (0) 2024.06.30
[JS 개념정리 1] script 태그 속성, ES6 module, strict mode, 화살표함수  (0) 2024.06.30
Next.js 프로젝트에 GA4 붙이기(사용자 속성, 잠재고객, UTM)  (0) 2024.06.16
[troubleshooting] yarn berry와 깃헙 액션 사용시 주의점 (Error: Cannot find module '.yarn/releases/yarn-3.6.4.cjs')  (4) 2023.10.13
'Programming/FE' 카테고리의 다른 글
  • [JS 개념정리 3] scope, 스코프 체인, 호이스팅, TDZ, 클로저
  • [JS 개념정리 1] script 태그 속성, ES6 module, strict mode, 화살표함수
  • Next.js 프로젝트에 GA4 붙이기(사용자 속성, 잠재고객, UTM)
  • [troubleshooting] yarn berry와 깃헙 액션 사용시 주의점 (Error: Cannot find module '.yarn/releases/yarn-3.6.4.cjs')
FoO__511
FoO__511
  • FoO__511
    FoO의 개발 블로그
    FoO__511
  • 전체
    오늘
    어제
    • 분류 전체보기 (17)
      • Programming (13)
        • Java (1)
        • Python (5)
        • Algorithm (2)
        • FE (5)
      • 학과공부 (2)
        • 데이터통신 (1)
        • 기계학습 (1)
        • 기타 (0)
      • 회고 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    javascript
    seaborn
    함수 빌려쓰기
    렉시컬 스코프
    결손치 제거
    jupyter extension
    function barrowing
    연습문제 풀이
    Priority Queue
    opencv-python으로 배우는 영상처리 및 응용
    Java
    결측치 제거
    TDZ
    opencv-python
    Git Action
    dinamic programming
    multi boot
    사용자 속성
    리눅스 카톡
    partial application
    script tag
    git workflow
    utm parameter
    nextjs
    kde plasma
    백준
    GA4
    개방 시스템 상호 연결
    연습문제 6장
    yarn berry
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
FoO__511
[JS 개념정리 2] call, apply, bind 메서드
상단으로

티스토리툴바