this 이것 - JavaScript에서
this
키워드는 다른 언어와 조금 다르게 동작한다.
this
는 앞으로 만들어질 인스턴스나 지금의 객체 자기 자신을 가리키는 자기 참조 변수(self-referencing variable)이다.
JavaScript에서는 문맥에 따라 this 이것이 가리키는 것이 달라진다.
this 바인딩은 this(키워드이지만 식별자 역할을 함)와 this를 가리킬 객체를 바인딩하는 것이다.
바인딩이란 식별자(변수)와 값을 연결하는 과정이다.
this를 사용하면서 나 자신의 인스턴스를 가리키는 것, 특정한 객체와 이 this를 묶어두는 것 등이 this 바인딩이다.
Java, C#,C++
등에서는 this 바인딩이 정적으로 결정된다. 즉 한 번 인스턴스를 가리키는 this가 결정이 되면 계속 그 인스턴스만 정적으로 가리킨다.
JavaScript, typeScript
에서 this는 런타임 상에서 함수 호출 방식에 따라 동적으로 this 바인딩이 결정된다. 따라서 개발자가 예상치 못한대로 코드가 흘러갈 수 있다.
전역 문맥에서 this
는 엄격 모드 여부에 관계 없이 전역 객체를 참조한다.
글로벌 컨텍스트의 this
브라우저: window
노드 : 모듈
console.log(this) // {}
const a = 0;
module.exports.a = a;
console.log(this); // { a: 0 }
console.log(globalThis); //전역 객체
전역 함수, 중첩 함수(nested function)를 일반 함수로 호출하면 함수 내부의 this에는 전역 객체가 바인딩된다.
globalThis
function f1() {
return this;
}
// 브라우저
f1() === window; // true
// Node.js
f1() === globalThis; // true
undefined
→ 함수 내부 스코프 안에 this 정보가 없기 때문이다.'use strict';
function f2() {
return this;
}
f2() === undefined; // true
function Cat(name) {
this.name = name;
this.printName = function () {
console.log(this.name);
};
}
const cat1 = new Cat('나비');
const cat2 = new Cat('춘배');
cat1.printName(); // 나비
cat2.printName(); // 춘배
함수를 어떤 객체의 메서드로 호출하면
this
의 값은 그 객체를 사용한다.
const person = {
name: "Kim",
getName() {
// 메서드 내부의 this는 메서드를 호출한 객체에 바인딩
return this.name;
},
};
// 메서드 getName을 호출한 객체는 person
console.log(person.getName()); // Kim
JavaScript는 누가 호출하냐에 따라 this가 달라지는 dynamic binding이다.
- 함수가 호출되는 상황 4가지
- 함수 호출 : 함수 직접 호출
- 메서드 호출 : 객체의 메서드 호출
- 생성자 호출 : 생성자 함수를호출
- 간접 호출 : call, apply 등으로 함수 간접 호출
function f() {
return this.a;
}
let g = f.bind({ a: 'azerty' });
console.log(g()); // azerty
let h = g.bind({ a: 'yoo' }); // bind는 한 번만 동작함!
console.log(h()); // azerty
let o = { a: 37, f: f, g: g, h: h };
console.log(o.a, o.f(), o.g(), o.h()); // 37, 37, azerty, azerty
call(this, var1, var2, var3, …)
apply(this, [ el, el2, el3, … ])
화살표 함수는 생성 시점의 렉시컬 환경에서의 this를 기억하고 고정한다. 즉, 정적 바인딩된다.
화살표 함수에서 this
는 자신을 감싼 정적 범위!
call, bind, apply를 사용해도 바뀌지 않는다.
전역 코드에서 화살표 함수 this → 자신을 감싼 전역 객체
let globalObject = this;
let foo = () => this;
console.log(foo() === globalObject); // true
const obj = {
method() {
console.log('context : ', this); // obj
let f1 = function () {
console.log('[f1] this : ', this);
};
let f2 = () => console.log('[f2] this : ', this);
f1(); // global
f2(); // obj -> this는 가장 근접한 스코프 obj 가리킴
},
};
o.method();
💡 대답할 수 있나요?
- 자바스크립트에서 this는 무엇이고, 어떻게 사용하나요?
- call, apply, bind에 대해 설명해주세요.
- 일반 함수의 this와 화살표 함수의 this는 어떻게 다른가요?
- setTimeout 에서 this는 왜 전역을 가리키는지 설명하세요.
참고자료
mozilla-this, velog, poimaweb