자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수
this
는 자신의 속성을 참조하는 자기 참조 변수로 자바스크립트에서 this는 문맥에 따라 가리키는 대상이 달리진다.
타언어와는 다르게 자바스크립트는 런타임 상에서 this
바인딩이 동적으로 결정되어 상황마다 다른 대상을 가르킨다.
이렇게 특정 객체마다 this
를 묶어놓은 것을 this바인딩
이라 한다.
this
: Window
console.log(this);
// Window {window: Window, self: Window, document: document, name: '', location: Location, …}
console.log(this.setTimeout);
// ƒ setTimeout() { [native code] }
console.log(setTimeout);
// ƒ setTimeout() { [native code] }
console.log(globalThis);
// Window {window: Window, self: Window, document: document, name: '', location: Location, …}
this
: 앞으로 생설될 인스턴스
// 생성자 함수
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(); // 미야옹
// 클래스 (엄격 모드)
'use strict';
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
: globalThis
, undefined
, Window
// 일반 함수
function fun() {
console.log(this);
}
fun(); // Object [global] {....}
// 일반 함수 (엄격 모드)
'use strict';
function fun() {
console.log(this);
}
fun(); // undefined
// 브라우저
function fun() {
console.log(this);
}
fun(); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
타 객체지향 프로그래밍 언어(자바
, C++
...등등)의 this
는 항상 자신의 인스턴스를 가르킨다.
즉 정적으로 인스턴스가 만들어지는 시점에 this
가 결정된다.
하지만 자바스크립트에서는 누가 호출하냐에 따라서 this
가 달라진다. 이는 호출하는 사람(caller)
에 의해 this
가 동적으로 결정된다고 할 수 있다.
function Cat(name) {
this.name = name;
this.printName = function () {
console.log(`고양이의 이름을 출력한다: ${this.name}`);
}
}
function Dog(name) {
this.name = name;
this.printName = function () {
console.log(`강아지의 이름을 출력한다: ${this.name}`);
}
}
const cat = new Cat('냐옹');
const dog = new Dog('멍멍');
dog.printName = cat.printName;
dog.printName(); // 고양이의 이름을 출력한다: 멍멍
cat.printName(); // 고양이의 이름을 출력한다: 냐옹
만약 호출하는 객체없이 함수를 실행하면 undefined
이 출력된다.
function Cat(name) {
this.name = name;
this.printName = function () {
console.log(`고양이의 이름을 출력한다: ${this.name}`);
}
}
function Dog(name) {
this.name = name;
this.printName = function () {
console.log(`강아지의 이름을 출력한다: ${this.name}`);
}
}
const cat = new Cat('냐옹');
const dog = new Dog('멍멍');
function printOnMonitor(printName) {
console.log('모니터를 준비한 뒤 전달된 콜백함수를 실행!');
// 호출하는 객체가 없기 때문에 this는 undefined가 할당
// object.printName();
printName();
}
printOnMonitor(cat.printName); // 고양이의 이름을 출력한다: undefined
자바스크립트에서는 동적 바인딩뿐만 아니라 정적 바인딩을 하는 방법이 존재한다.
bind
: this
를 수동적으로 바인딩function Cat(name) {
this.name = name;
this.printName = function () {
console.log(`고양이의 이름을 출력한다: ${this.name}`);
}
this.printName = this.printName.bind(this);
}
function Dog(name) {
this.name = name;
this.printName = function () {
console.log(`강아지의 이름을 출력한다: ${this.name}`);
}
}
const cat = new Cat('냐옹');
const dog = new Dog('멍멍');
dog.printName = cat.printName;
dog.printName(); // 고양이의 이름을 출력한다: 냐옹
cat.printName(); // 고양이의 이름을 출력한다: 냐옹
arrow function
: 화살표 함수는 렉시컬환경의 this
를 기억, 화살표 함수 밖에서 제일 근접한 스코프의 this
를 가르킨다.function Cat(name) {
this.name = name;
this.printName = () => {
console.log(`고양이의 이름을 출력한다: ${this.name}`);
}
}
function Dog(name) {
this.name = name;
this.printName = function () {
console.log(`강아지의 이름을 출력한다: ${this.name}`);
}
}
const cat = new Cat('냐옹');
const dog = new Dog('멍멍');
dog.printName = cat.printName;
dog.printName(); // 고양이의 이름을 출력한다: 냐옹
cat.printName(); // 고양이의 이름을 출력한다: 냐옹
전통적인 함수표현(function)의 간편한 대안
화살표함수(arrow function)
는 기존의 함수보다 문법이 깔끔하고, 생성자 함수로도 사용이 불가능하여 무거운 프로토타입을 생성하지 않는다.
그리고 this
에 대한 바인딩이 정적으로 결정된다. 이 때 결정된 this
는 함수에서 제일 근접한 상위 스코프의 정적으로 바인딩 된다.
const cat = {
name: 'Cat',
play () {
console.log('냐옹');
},
};
const printArrow = () => {
console.log(this);
}
cat.printArrow = printArrow;
cat.printArrow(); // {} => cat객체를 감싸고 있는 전역객체를 출력
this - JavaScript | MDN
화살표 함수 - JavaScript
모던 자바스크립트 Deep Dive
모던 JavaScript 튜토리얼