이 글은 '이웅모'님의 '모던 자바스크립트 Deep Dive' 책을 통해 공부한 내용을 정리한 글입니다. 저작권 보호를 위해 책의 내용은 요약되었습니다.
this
는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수를 뜻한다. this
를 통해 자신이 속한 객체 또는 자신이 생성할 인스턴스의 프로퍼티나 메서드를 참조할 수 있다.
자바스크립트에서 this
는 상황에 따라 달리 바인딩된다. 즉, 함수 호출 방식에 의해 동적 바인딩된다. 이 부분이 처음 JS에서 this
를 사용할 때 어려운 부분인 것 같다. C++ 또는 Java 같은 클래스 기반 언어에서는 this
는 언제나 클래스가 생성한 인스턴스를 가리키기 때문에 헷갈리기 쉽다.
요약
this
, 내부 함수에서의 this
: 전역 객체(window, global)this
: 메서드를 호출한 객체this
: 생성자 함수가 생성할 인스턴스this
: 상위 스코프의 this
this
: 이벤트를 발생시킨 객체함수 호출 방식은 다음과 같이 다양하다. 함수 호출 방식에 따른 this 바인딩을 알아보도록 하겠다.
기본적으로 this
에는 전역 객체(Global Object)가 바인딩된다.
function a() {
console.log("a this : ", this); // a this : window
function b() {
console.log("b this : ", this); // b this : window
}
b();
}
a();
const obj = {
foo() {
function a() {
console.log("obj a this : ", this); // obj a this : window
}
a();
}
};
obj.foo();
이처럼 일반함수에서의 this
는 아무런 의미가 없다. 만약 strict mode
가 적용된다면 함수 내부의 this
에는 undefined
가 바인딩 된다.
function a() {
'use strict';
console.log("a this : ", this); // a this : undefined
}
a();
중첩함수, 콜백함수이라 할지라도 일반함수로 호출된다면 this
에는 전역 객체가 바인딩된다. 따라서 apply
call
bind
함수를 통해 this
를 바인딩하거나 화살표 함수를 활용한다.
메서드 내부의 this
에는 메서드를 호출한 객체가 바인딩된다.
const obj = {
name: 'kim',
getName() {
return this.name;
}
};
const anotherObj = {
name: 'Lim',
};
console.log(obj.getName()); // kim
anotherObj.getName = obj.getName;
console.log(anotherObj.getName()); // Lim
메서드 내부의 this
는 메서드를 소유한 객체가 아닌 메서드를 호출한 객체에 바인딩된다는 것에 주의한다.
생성자 함수 내부의 this
에는 생성자 함수가 앞으로 생성할 인스턴스가 바인딩된다.
function Foo(number) {
this.number = number;
this.square = function() {
return this.number * this.number;
}
}
const a = new Foo(5);
console.log(a.square()); // 25
apply
와 call
메서드의 본질적인 기능은 함수를 호출하는 것이다. 함수를 호출하면서 첫 번째 인수로 전달한 특정 객체를 호출한 함수의 this
에 바인딩한다. 이 둘의 차이점은 함수 인수를 전달하는 방법에 있을 뿐, 동작 방식은 동일하다.
function getThis() {
console.log(arguments);
return this.name;
}
const obj = { name : 'kim' };
console.log(getThis.apply(obj, [1,2,3]));
// Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
// kim
console.log(getThis.call(obj, 1, 2, 3,));
// Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
// kim
bind
메서드는 apply
와 call
메서드와 달리 함수를 호출하지 않는다. 첫 번째 인수로 전달한 값으로 this 바인딩이 교체된 함수를 새롭게 생성해 반환한다. bind
메서드는 화살표 함수가 나오기 전까지 메서드의 this
와 중첩 또는 콜백 함수의 this
가 불일치 하는 문제를 해결하는데 유용하게 사용되었다.
function getThis() {
return this.name;
}
const obj = { name : 'kim' };
console.log(getThis.bind(obj)()); // kim
화살표 함수(Arrow Function)은 일반적인 동적 this
바인딩과는 다르게 정적 this
바인딩을 가진다. 즉 Lexical this
를 가진다. 화살표 함수의 this
는 언제나 상위 스코프의 this
를 가리킨다. 그래서 화살표 함수는 this
가 없다고도 표현한다.
const obj = {
name : 'kim',
whatIsYourName () {
const arrow = () => this.name;
console.log(arrow()); // kim
const nomal = function() {
return this.name;
}
console.log(nomal()); // undefined
}
};
obj.whatIsYourName();
이벤트 리스너에서 this
는 이벤트를 발생시킨 객체에 바인딩된다.
const button = document.querySelector('#button');
button.onclick = function () {
console.log(this); // button
};