JS에서 this와 binding

KB LEE·2025년 6월 11일
0

JavaScript 펼쳐보기

목록 보기
1/6
post-thumbnail

this?

JavaScript에서 this는 함수가 호출되는 방식에 따라 동적으로 결정되는 값입니다.
타언어에선 클래스 인스턴스를 가르키지만 JS에선 실행 컨텍스트에 따라 값이 달라지기 때문에 혼란스러울 수 있습니다.

this가 참조하는 것은 함수가 호출되는 방식에 따라 결정되는데, 이것을 "this binding"


바인딩

JS에서 binding하는 것은 함수의 this 값을 명시적으로 고정하는 행위를 말합니다.
하지만 binding을 진행할 때, 여러 방법과 유의할 점이 존재합니다.

기본 바인딩

함수가 독립적으로 호출될 때 적용되는 기본 규칙
기본 this는 브라우저일 경우 window, node환경일 경우 global

단, strict mode일 경우, this는 undefined로 정의됩니다.
⇒ 이는 의도치 않는 전역 객체 접근을 방지

암시적 바인딩

this가 객체의 속성으로 등록된 함수에서 자동으로 객체를 가리키도록 결정되는 규칙
함수가 객체의 메서드로 호출될 때, this는 그 메서드를 소유한 객체를 가르킵니다.

// 암시적 바인딩의 예시
const person = {
  name: 'KB',
  greet() {
    console.log(`Hello, ${this.name}`);
  }
};
person.greet(); // Hello, KB

// 중첩된 객체에서의 암시적 바인딩
const outer = {
  name: 'Outer',
  inner: {
    name: 'Inner',
    getName() {
      return this.name;
    }
  }
};

하지만 참조가 끊기면 암시적 바인딩도 무력화

⇒ 객체의 메서드를 변수나 인자로 전달하는 순간, 그 메서드가 객체와의 연결(참조 관계)을 잃게 되어 this가 더 이상 객체를 가리키지 않게 된다.

const user = {
  name: 'KB',
  sayHi() {
    console.log(this.name);
  }
};

const fn = user.sayHi; // 메서드만 분리됨
fn(); // undefined (브라우저에선 window.name)

setTimeout(user.sayHi, 1000); // undefined

명시적 바인딩

call, apply, bind 함수를 통해 this를 설정하는 방법

Call

this를 명시하여 즉시 실행

// thisArg: 함수 실행 시 사용할 this
// arg1, arg2: 함수에 전달할 실제 인자들
Funciton.call(thisArg, arg1, arg2, ...);

// 예제
function callMe(prefix) {
	console.log(`${prefix}, My name is ${this.name}`);
}

const profile = { name: "KB" };

callMe.call(profile, "Hi"); // Hi, My name is KB

apply

call과 동일한 역할이지만 인자를 배열로 전달

Function.apply(thisArg, [arg1, arg2, ...]);

// 예제
function callMe(prefix) {
	console.log(`${prefix.join("|")}, My name is ${this.name}`);
}

const profile = { name: "KB" };

callMe.call(profile, ["Hi", "안녕"]); // Hi|안녕, My name is KB

bind

this를 고정한 새로운 함수를 반환

const bindFunction = Function.bind(thisArg, arg1, arg2, ...);

// 예제
function callMe(prefix) {
	console.log(`${prefix}, My name is ${this.name}`);
}

const profile = { name: "KB" };

const bindCallMe = callMe.bind(profile, "Hi");
bindCallMe(); // Hi, My name is KB

단, bind로 고정된 this는 변경되지 않습니다. (하드 바인딩, 영구 바인딩)

new 바인딩

생성자 함수가 new 키워드와 함께 호출될 때 적용되는 규칙

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

const KB = new Person("KB");

화살표함수

Arrow Function은 자신만의 this를 가지지 않습니다.
정의될 당시의 외부 스코프의 this를 그대로 캡쳐하여 사용합니다.

// 예시1
const user = {
  name: 'KB',
  sayHi() {
    const inner = () => {
      console.log(this.name);
    };
    inner();
  }
};

user.sayHi(); // KB

// 예시2
class Counter {
  count = 0;

  increase = () => {
    this.count++;
    console.log(this.count);
  };
}

const c = new Counter();
const inc = c.increase;
inc(); // 1 (this 유지됨)

주의해야할 점은 Arrow Funciton은 call, apply, bind를 무시합니다


정리

결국 bind를 이해한다는 것은 단순한 메서드 하나를 아는 것이 아니라, JavaScript 함수가 어떻게 실행되고, 바인딩되며, 어떤 식으로 제어 가능한지를 이해한다는 것입니다.

JavaScript의 bind()는 단순한 문법 sugar가 아닙니다.

본질은 함수의 실행 컨텍스트(this)를 명시적으로 제어하고 선택적으로 인자까지 고정할 수 있는 도구입니다.

특히 JS의 함수가 일급 객체이자 실행 컨텍스트에 따라 동적으로 this가 결정되는 언어 특성을 고려하면, bind()는 이런 동적 바인딩을 정적으로 "묶어버리는(bind)" 아주 강력한 수단입니다.

다음엔 더 유익한 글로 찾아오겠습니다.

profile
한 발 더 나아가자

0개의 댓글