[TIL #3] this, call(), apply(), bind()

2024. 8. 12. 21:12·Camp/T.I.L.

어쩌면 C를 처음 배울 때 포인터에서 느끼는 벽 이상의 무언가를 느끼게 해주는 존재.

``this``는 포인터는 아니지만 어떤 함수의 컨텍스트를 참조한다는 점에서 유사하기도 하다.

 

1. this

``this``는 다음과 같은 특징을 가진다.

  1. 실행 컨텍스트
     - ``this``는 함수가 호출될 때 그 함수의 실행 컨텍스트에 따라 값이 결정된다.
    이 실행 컨텍스트는 함수가 어떻게 호출되었느냐에 따라 달라진다.
    예를 들어, 객체의 메서드로 호출되면 그 객체가 ``this``가 되고,
    단순히 함수로 호출되면 전역 객체(``window`` 또는 ``global``)가 ``this``가 된다.
  2. 동적 바인딩
    - ``this``는 런타임에 결정되는 동적 바인딩을 사용한다.
    ``this``가 가리키는 대상은 함수가 호출될 때마다 달라질 수 있다.
    이는 ``call()``, ``apply()``, ``bind()``와 같은 함수를 통해 명시적으로 변경할 수 있다.
  3. 포인터와의 차이
    - 포인터는 메모리 주소를 직접 가리키며, 특정 데이터의 위치를 직접적으로 참조한다.
    반면, ``this``는 특정 데이터나 객체를 가리키는 것이 아니라, 함수가 실행되는 맥락을 참조한다.
    이는 일반적으로 객체 자신을 가리키지만, 그 자체로는 메모리 주소를 직접 다루는 것이 아니다.

 

아래 예시 코드를 통해 ``this``의 동작을 확인할 수 있다.

var obj1 = {
	outer: function() {
		console.log(this); // (1)
		var innerFunc = function() {
			console.log(this); // (2), (3)
		}
		innerFunc();

		var obj2 = {
			innerMethod: innerFunc
		};
		obj2.innerMethod();
	}
};
obj1.outer();


// 실행 결과
// (1): {outer: ƒ}
// (2): global {global: global, clearImmediate: ƒ, setImmediate: ƒ, clearInterval: ƒ, clearTimeout: ƒ, …}
// (3): {innerMethod: ƒ}

 

 

2. call()

``call()`` 메서드는 함수를 호출하면서 ``this`` 값을 특정 객체로 설정할 수 있다.

첫 번째 인자로 ``this``로 사용할 값을 전달하고, 그 뒤의 인자들은 호출할 함수에 전달한다.

 

function greet(greeting, punctuation) {
    console.log(greeting + ', ' + this.name + punctuation);
}

var person = {
    name: 'Alice'
};

// call을 사용하여 this를 person 객체로 설정하고 인자를 전달
greet.call(person, 'Hello', '!');

// 출력: "Hello, Alice!"

``greet``는 ``person``을 ``this``로 하여 호출된 것이다.

 

 

3. apply()

``apply()`` 메서드는 ``call()``과 비슷하지만, 인자들을 배열로 전달해야 한다는 점에서 차이가 있다.

첫 번째 인자는 ``this``로 사용할 값이고, 두 번째 인자는 함수에 전달할 인자들이 담긴 배열이다.

 

var numbers = [10, 20, 3, 16, 45];
var max = Math.max.apply(null, numbers);
var min = Math.min.apply(null, numbers);
console.log(max, min);

``apply()``는 배열로 전달된 인자들을 개별 인자들로 나누어 함수에 전달한다.

 

하지만 일반 배열의 사이즈가 매우 크다면?

매우 많은 양을 일일이 하드코드 할 수 없을 것이다.

이때, Spread Operator를 사용해 더 편하게 해결할 수 있다.

 

const numbers = [10, 20, 3, 16, 45];
const max = Math.max(...numbers);
const min = Math.min(...numbers);
console.log(max min);

``...``는 배열의 요소들을 펼쳐서(Spread) 일일이 인수로 넣어준 것과 같이 만들어 준다.

 

 

4. bind()

``bind()`` 메서드는 this 값을 고정한 새로운 함수를 생성한다.

즉, ``bind()``는 즉시 함수를 호출하지 않고, this 값과 인자를 고정한 새로운 함수를 반환한다.

반환된 함수를 나중에 호출할 수 있다.

 

function Person(name) {
    this.name = name;
}

Person.prototype.greet = function () {
    console.log(`Hello, my name is ${this.name}`);
};

const person1 = new Person('Bob');
const greet = person1.greet

greet(); // 출력: "Hello, my name is undefined"

const boundGreet = person1.greet.bind(person1);
boundGreet(); // 출력: "Hello, my name is Bob"

여기서 ``person1.greet.bind(person1)``는 ``this``를 ``person``으로 고정한다.

 

그리고, ``bind`` 메서드를 적용해서 새로 만든 함수는 ``name`` 프로퍼티에 ‘bound’라는 접두어가 붙는다.

따라서 추적하기가 매우 용이하다.

var func = function (a, b, c, d) {
	console.log(this, a, b, c, d);
};
var bindFunc = func.bind({ x:1 }, 4, 5);

// func와 bindFunc의 name 프로퍼티의 차이를 살펴보세요!
console.log(func.name); // func
console.log(bindFunc.name); // bound func

위 예시 코드처럼 ``name``을 출력하게 되면,

``bind``된 메서드는 앞에 ``bound``라는 접두어가 붙는 것을 확인할 수 있다.

 

 

5. 정리

  • call()
    - 함수 호출 시 ``this``를 특정 객체로 설정하고, 인자들을 개별적으로 전달한다.
  • apply()
    - 함수 호출 시 ``this``를 특정 객체로 설정하고, 인자들을 배열로 전달한다.
  • bind()
    - ``this``를 특정 객체로 고정한 새로운 함수를 생성하고, 고정된 인자들을 추가로 설정할 수 있다.
    함수는 나중에 호출될 수 있다.

 

아래의 기본 객체가 있다고 가정하자.

var car = {
    brand: 'Toyota',
    getBrand: function() {
        return this.brand;
    }
};

var bike = {
    brand: 'Honda'
};

 

그럼 다음의 사용 예시를 확인할 수 있다.

// call 사용
console.log(car.getBrand.call(bike)); // "Honda"

// apply 사용
console.log(car.getBrand.apply(bike)); // "Honda"

// bind 사용
var getBikeBrand = car.getBrand.bind(bike);
console.log(getBikeBrand()); // "Honda"

셋 다 ``this``에 ``bike``를 넘겨주기 때문에 "Honda"를 리턴하게 된다.

 

``this``에 대해 확실히 공부해 둘 필요성이 대단히 높다.

JS의 객체지향을 위해서라도 필요한 부분이다.

'Camp > T.I.L.' 카테고리의 다른 글

[TIL #5] 소수 만들기  (0) 2024.08.22
[TIL #4] 비동기  (0) 2024.08.13
[KPT 회고] 팀 소개 페이지 미니 프로젝트에 대한 회고  (0) 2024.08.09
[TIL #2] 간단한 API 프록시 서버 구현  (0) 2024.08.09
[TIL #1] 명세  (0) 2024.08.05
'Camp/T.I.L.' 카테고리의 다른 글
  • [TIL #5] 소수 만들기
  • [TIL #4] 비동기
  • [KPT 회고] 팀 소개 페이지 미니 프로젝트에 대한 회고
  • [TIL #2] 간단한 API 프록시 서버 구현
BVM
BVM
  • BVM
    E:\
    BVM
  • 전체
    오늘
    어제
    • 분류 전체보기 (168)
      • Thoughts (14)
      • Study (69)
        • Japanese (3)
        • C++ & C# (46)
        • Javascript (3)
        • Python (14)
        • Others (3)
      • Play (1)
        • Battlefield (1)
      • Others (11)
      • Camp (73)
        • T.I.L. (57)
        • Temp (1)
        • Standard (10)
        • Challenge (3)
        • Project (1)
  • 블로그 메뉴

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

  • 공지사항

    • 본 블로그 개설의 목적
  • 인기 글

  • 태그

    Python
    클라우드
    C++
    discord
    FF14
    Selenium
    Server
    Dalamud
    서버
    암호화
    프로그래머스
    bot
    boost
    OSI
    cloudtype
    로깅
    JS
    네트워크 프로그래밍
    포인터
    c#
    스타필드
    네트워크
    IOCP
    Network
    베데스다
    docker
    discord py
    7계층
    db
    Asio
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
BVM
[TIL #3] this, call(), apply(), bind()
상단으로

티스토리툴바