본문으로 건너뛰기
김신건의 로그

[Javascript] this 바인딩

· 수정 · 📖 약 1분 · 317자/단어 #javascript #this #binding #fundamentals
JS this 바인딩, JS this, JS this binding, call apply bind

정의

JavaScript 의 this호출 방식에 따라 결정 되는 동적 바인딩. 4 가지 호출 방식 + arrow function (lexical) 규칙.

5 가지 규칙

#규칙this 값
1일반 호출fn()undefined (strict) / globalThis
2메서드 호출obj.fn()obj
3명시적fn.call(x), fn.apply(x)x
4생성자new Fn()새 인스턴스
5화살표() => {}lexical (정의 위치)

메서드 vs 일반 호출

const obj = {
    name: 'Alice',
    greet() { return this.name; }
};

obj.greet();             // 'Alice' (메서드 호출)
const fn = obj.greet;
fn();                     // undefined (일반 호출, strict)

함수를 변수에 담는 순간 컨텍스트 손실.

call / apply / bind

fn.call(thisArg, arg1, arg2);
fn.apply(thisArg, [arg1, arg2]);
const bound = fn.bind(thisArg, arg1);
  • call: 즉시 호출, 인자 쉼표
  • apply: 즉시 호출, 인자 배열
  • bind: 새 함수 반환 (this 영구 바인딩)
function greet(prefix, suffix) {
    return `${prefix} ${this.name} ${suffix}`;
}
greet.call({name: 'A'}, 'Hi', '!');     // 'Hi A !'
greet.apply({name: 'A'}, ['Hi', '!']);  // 'Hi A !'
const bound = greet.bind({name: 'A'}, 'Hi');
bound('!');                              // 'Hi A !'

화살표 함수의 lexical this

class Counter {
    constructor() {
        this.count = 0;
        setInterval(() => {
            this.count++;        // ✓ Counter 인스턴스의 this
        }, 1000);
    }
}

화살표 함수는 자체 this 가 없다. 정의 위치의 this 를 사용. arrow function 참고.

일반 함수였다면

setInterval(function() {
    this.count++;        // ❌ this 는 globalThis 또는 undefined
}, 1000);

// 옛 해결책
const self = this;
setInterval(function() {
    self.count++;
}, 1000);

new 호출

function Person(name) {
    this.name = name;     // 새 객체에 할당
}
const p = new Person('Alice');
p.name;                    // 'Alice'

new 호출 시:

  1. 새 빈 객체 생성
  2. [[Prototype]] = Person.prototype
  3. this = 새 객체
  4. 함수 실행
  5. 명시적 return 객체 없으면 새 객체 반환

이벤트 핸들러

button.addEventListener('click', function() {
    console.log(this);    // button (DOM element)
});

button.addEventListener('click', () => {
    console.log(this);    // 외부 스코프의 this (window 등)
});

DOM 이벤트는 일반 함수면 this = 이벤트 타겟. 화살표 함수면 외부 this.

class 메서드의 this

class Btn {
    constructor() { this.clicks = 0; }
    onClick() { this.clicks++; }      // this 손실 위험
}

const b = new Btn();
button.addEventListener('click', b.onClick);   // ❌ this 가 button
button.addEventListener('click', b.onClick.bind(b));   // ✓
button.addEventListener('click', () => b.onClick());   // ✓

class Btn2 {
    clicks = 0;
    onClick = () => this.clicks++;    // ✓ class field arrow, auto bound
}

우선순위

1. new 바인딩 (가장 강함)
2. 명시적 (call/apply/bind)
3. 메서드 호출
4. 일반 호출 (가장 약함)
const a = { name: 'a' };
const b = { name: 'b' };

function greet() { return this.name; }
const bound = greet.bind(a);
bound.call(b);    // 'a' (bind 가 call 보다 우선)

함정

1. arrow 함수에 call 무의미

const fn = () => this;
fn.call({ x: 1 });        // 외부 this 그대로 반환

2. 메서드 분리

const obj = { greet() { return this; } };
const m = obj.greet;
m();    // undefined (강제 변환 없는 strict 모드)

3. nested 함수

const obj = {
    name: 'A',
    outer() {
        function inner() {
            return this.name;     // undefined!
        }
        return inner();
    }
};

해결: 화살표 함수 또는 변수 보존.

참고

이 글의 용어 (5개)
[Javascript] Arrow Functionjavascript
정의 화살표 함수 (arrow function) 는 ES2015 (ES6) 에서 도입된 함수 표현식. 모양. 더 짧은 문법뿐 아니라 가 lexical 로 바인딩 되는 본질적 차이…
[Javascript] Classjavascript
정의 ES6 는 prototype chain 위의 문법 설탕. C++/Java 스타일 OOP 와 닮았지만 내부는 . 구조 상속 super 의 의미 - : 부모 constructo…
[Javascript] functionjavascript
정의 은 JavaScript 에서 함수를 만드는 가장 기본적인 키워드. 호이스팅, 동적 바인딩, 객체, 호출 등 과 구분되는 고유한 특성을 가진다. 함수가 값 으로 다뤄지는 의 …
[Javascript] Lexical Environmentjavascript
정의 Lexical Environment (어휘적 환경) 는 ECMAScript 명세 (§9.1) 가 정의한 내부 객체. 함수가 호출될 때마다 새로 만들어지며, 이 호출의 변수들…
[Javascript] Prototype Chainjavascript
정의 JavaScript 의 모든 객체는 (내부 슬롯) 을 가진다. 속성 lookup 시 자신에게 없으면 prototype chain 을 따라 올라가며 검색. 접근 함수의 pro…

이 개념을 다룬 위키 페이지 (1)

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기