This(2)

2ㅣ2ㅣ·2024년 4월 2일

JavaScript

목록 보기
10/14
post-thumbnail

이전에 this의 기본 개념에 대해 알아보았다. 이번 포스팅에서는 this 바인딩의 구체적인 방법들에 대해 살펴보겠다. JavaScript에서는 this가 함수 실행 컨텍스트에 따라 다르게 바인딩된다. 크게 암시적 바인딩, 명시적 바인딩, new 바인딩, 그리고 기본 바인딩으로 나뉜다. 🤯

암시적 바인딩

자바스크립트에서 객체의 메서드로 함수를 호출할 때, this는 그 메서드를 호출한 객체에 자동으로 바인딩된다. 다시 말해, 메서드 내부에서 this를 사용하면, 그 메서드를 소유하고 있는 객체를 가리키게 된다.

const obj = {
	name: 'kim',
	getName() {
		return this.name; // this = obj 즉, obj.name과 같음
	}
};

여기서 obj.getName()을 호출하면, thisobj를 가리키므로, this.name'kim'을 반환한다.

명시적 바인딩

함수의 this를 명시적으로 지정할 수 있는 방법이다. 주로 apply, call, bind 메서드를 사용한다.

apply, call 사용: 즉시 실행

function greet(location, timeOfDay) {
  console.log(`Good ${timeOfDay}, I'm ${this.name} from ${location}.`);
}

const user = {
  name: 'Emma'
};

// call을 사용하여 즉시 실행
greet.call(user, 'New York', 'morning');

// apply를 사용하여 즉시 실행
greet.apply(user, ['London', 'evening']);
  • applycall은 함수를 즉시 실행하면서 첫 번째 인자로 this에 바인딩할 객체를 전달한다.
  • 차이점은 apply는 함수에 전달할 인자를 배열로 받고, call은 인자를 하나씩 전달한다.
  • 그런데 왜 이런 방법을 사용할까? 🥵
    • 이는 함수형 프로그래밍의 특성 때문이다. 함수를 다른 함수의 인자로 전달하거나, 함수에서 또 다른 함수를 반환하는 고차 함수의 개념을 활용할 때, this를 유연하게 바인딩할 수 있는 기능이 필요하다.

bind 사용: 새로운 함수 반환받기

function logActivity(activity) {
  console.log(`${this.name} is ${activity}.`);
}

const user = {
  name: 'Tom'
};

// bind를 사용하여 함수 반환받음
const tomLogActivity = logActivity.bind(user);

// 나중에 이벤트 핸들러나 콜백으로 사용
setTimeout(tomLogActivity, 1000, 'running');
  • bind 메서드는 함수의 this를 영구히 바꿀 수 있다. 첫 번째 인자로 전달된 객체에 this를 고정한 새로운 함수를 반환한다.
  • applycall이 함수를 즉시 실행한다면, bind는 새로운 함수를 반환하기 때문에, 언제든지 호출할 수 있는 함수를 만들어낼 수 있다.

💡 new 바인딩

new 키워드를 사용하여 함수를 생성자로 호출하면, 함수 내부에서의 this는 새로 생성된 객체에 바인딩된다. 이렇게 생성된 객체는 해당 함수의 프로토타입을 상속받는다.

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

const jay = new Person('jay', 23);
console.log(jay); // Person { name: 'jay', age: 23 }

만약 new를 사용하지 않고 생성자 함수를 호출한다면, this는 전역 객체(브라우저에서는 window, Node.js에서는 global)에 바인딩되거나, 엄격 모드에서는 undefined가 된다.

new 바인딩에서 제공하는 프로토타입 상속

그 이점은 무엇일까? 바로 코드로 살펴보자.

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

Person.prototype.introduce = function() {
  console.log(`My name is ${this.name}.`);
};

const person1 = new Person("Alice");
const person2 = new Person("Bob");

// person1과 person2는 Person.prototype.introduce 메서드를 공유.
person1.introduce(); // My name is Alice.
person2.introduce(); // My name is Bob.
  • 재사용 가능한 코드: 공통 로직을 프로토타입에 정의함으로써, 모든 인스턴스가 이 로직을 공유할 수 있다. 이는 코드 중복을 줄이고, 유지 보수성을 향상시킨다.
  • 메모리 효율성: 인스턴스마다 메서드를 복사하지 않고, 프로토타입의 메서드를 공유함으로써 메모리 사용량을 최소화할 수 있다.
  • 동적 속성/메서드 추가: 프로토타입에 속성이나 메서드를 추가하면, 해당 생성자로 생성된 모든 객체에 즉시 반영된다. 이는 런타임 중에 객체의 행동을 동적으로 변경할 수 있는 유연성을 제공한다.

👑 우선순위

this 바인딩의 우선순위는 다음과 같다

  1. new 바인딩: 생성자 함수로 호출될 때
  2. 명시적 바인딩: apply, call, bind를 사용할 때
  3. 암시적 바인딩: 객체의 메서드로 호출될 때
  4. 기본 바인딩: 그 외의 경우

이러한 규칙을 이해하고 있으면, 다양한 상황에서 this의 값을 예측하는 데 도움이 된다.

this 바인딩 중요한 이유 ❓

  • 고차 함수와 커링
    • 함수형 프로그래밍에서 함수는 일급 객체로, 다른 함수의 인자로 전달되거나, 함수에서 또 다른 함수를 반환할 수 있다.
    • 이때 this 바인딩을 명확하게 관리하면, 고차 함수나 커링(currying) 기법을 효과적으로 사용할 수 있다.
  • 함수 재사용과 컴포지션
    • 함수형 프로그래밍에서는 작은 함수를 조합하여 더 큰 기능을 구현하는 컴포지션을 중시한다.
    • this 바인딩을 유연하게 다루면, 다양한 객체나 컨텍스트에서도 함수를 재사용할 수 있어, 코드의 재사용성과 모듈성이 향상된다.

정리

이번 포스팅에서는 this 바인딩에 대한 다양한 방법과 우선순위를 알아보았습니다. 이를 통해 this의 동작 방식을 보다 명확하게 이해할 수 있기를 바랍니다.


출처
✔️ 유튜브별코딩
✔️ poiemaweb

profile
https://sususoo.tistory.com/

0개의 댓글