자바스크립트를 통해 개발하다보면 가끔보게 되는 키워드가 있는데, 바로 `this`라는 키워드이다.
보통 `this` 라고 하면 인스턴스 본인을 가리킬때 사용하는 키워드이다. 하지만 자바스크립트에서는 이 `this`가 다른 언어와 조금은 다르게 바인딩되는 경우들이 있다.
이번 글에서는 위와 같은 경우가 어떤 상황에서 발생하는지 정리해보려고 한다.
this 를 출력해보자
F12키를 눌러 console에서 this를 한번 찍어보면 아래와 같은 값이 나오게 된다.
> this
> Window {
applicationCache: ApplicationCache {status: 0,
LocalNTP: ƒ LocalNTP()
alert: ƒ alert() oncached: null…}
assert: ƒ assert(condition, opt_message)
assertInstanceof: ƒ assertInstanceof(value, type, opt_message)
...
}
Window 객체가 나오게 된다. 기본적으로 Window 객체는 브라우저의 요소와 자바스크립트 엔진과 관련된 모든 정보를 포함하고 있는 객체로 바인딩된다.
사용하는 문법에 따라 this가 변한다?
예전에 커뮤니티에 이런 글이 하나 올라왔었다.
질문: function 과 () => {} (화살표 함수)의 차이점이 무엇인가요?
댓글 A: "this가 달라요"
댓글 B: "function은 this를 가지고, 화살표함수는 this를 가지지 않아요"
틀린 답변은 아니지만, 정확히 어떻게 this가 다르다는 걸까?
말 그대로 생각했을 때, 아래 코드처럼 생각해볼 수 있다.
// 서로 다른 값이 출력??
function normalFunc() {
console.log(this);
}
const arrowFunc = () => {
console.log(this);
};
"function은 this를 가지니까 자기자신 즉 normalFunc를 가리키고, 화살표함수는 this를 안가지니까 Window 함수를 가지겠구나?" 라고 생각할 수 있지만, 출력해보면 둘 다 Window 객체를 출력하는 것을 알 수 있다.
그럼 대체 뭐가 다른걸까? 우선 실행 컨텍스트라는 개념을 알아야 한다.
실행 컨텍스트(Execution Context)
실행 컨텍스트란 자바스크립트 코드가 실행되고 연산되는 범위를 나타내는 추상적인 개념이다. 코드가 실행된다면 실행 컨텍스트 내부에서 작동하고 있는 것이다.
실행 컨텍스트는 크게 3가지로 분류되는 데, 메인 주제에 해당하는 주요한 2가지는 다음과 같다.
(자세한 내용은 이전에 정리한 실행 컨텍스트 글 참조)
Global Execution Context
- 기본적으로 코드가 실행되는 영역이며, 여기서 글로벌 객체인 Window 객체를 생성하며, this를 글로벌 객체(Window 객체)로 바인딩 해준다.
- (그래서 아까 처음에 this를 찍었을 때, Window 객체가 출력된 것이다.)
Functional Execution Context
- 각각의 함수가 가지는 실행 컨텍스트로, 함수가 호출될 때 해당 실행 컨텍스트가 생성된다.
언제 this가 바뀔까
this는 기본적으로 Window 객체를 말한다. (Node.js는 Global 객체)
하지만 this의 값이 바뀌는 경우가 있다. 때문에 this 값이 어떻게 바뀌고 있는지, 해당 this가 무슨 값인지 알기 위해선 코드의 문맥을 살펴볼 필요가 있다.
1. 객체의 메소드를 호출하는 경우
const myObj = {
myValue: 6,
myWindow: this,
myFunc: function () {
console.log(this);
},
myArrow: () => {
console.log(this);
},
};
console.log(myObj.myFunc()); // myObj 객체
console.log(myObj.myArrow()); // Window 객체
출력되는 this의 값이 바뀌었다는 것을 알 수 있다. 이를 MDN 문서에서는 아래와 같이 설명하고 있다.
함수를 어떤 객체의 메소드로 호출하면 this의 값은 그 객체를 사용합니다.
ES2015는 스스로의 this 바인딩을 제공하지 않는 화살표 함수를 추가했습니다.
- MDN web docs -
이것이 아까 위에서 나왔던 답변의 정확한 의미이다. function 키워드는 해당 객체를 바인딩하여 `this`의 값을 변경하는 것이고, 화살표 함수는 상위 컨텍스트의 `this`를 그대로 바인딩하여 사용하는 것이다.
2. 생성자를 통해 객체를 생성하는 경우
function Programmer(name, age) {
this.name = name;
this.age = age;
}
// 생성자를 사용하지 않은 경우 - 단순 호출
const covy = Programmer('Covy', 20); // covy 변수는 undefined
console.log(window.name, window.age); // Covy 20
// 생성자를 통한 객체 생성
const tony = new Programmer('Tony', 25);
console.log(tony.name, tony.age); // Tony 25 - this가 해당 객체에 바인딩됨
`new` 키워드를 통해 객채를 생성하면, this가 해당 객체에 바인딩 되어 해당 값을 읽게 된다.
es6에 추가된 `class` 키워드를 사용하면 동일하게 작동하는 것을 볼 수 있다.
apply(), call(), bind()
자바스크립트에서는 `this`를 자유자제로 바꿀 수 있도록 해주는 메소드를 제공하는 데, 바로 `apply`, `call`, `bind` 이다.
ES5는 함수를 어떻게 호출했는지 상관하지 않고 this 값을 설정할 수 있는 bind 메서드를 도입했습니다.
-MDN web docs-
const Tom = {
age: 25,
gender: 'man',
};
function printProfile(name) {
console.log(name, this.age, this.gender);
}
printProfile.apply(Tom, ['Tom']); // Tom 25 man
printProfile.call(Tom, 'Tom'); // Tom 25 man
printProfile.bind(Tom, 'Tom').call(); // Tom 25 man
- apply: call 함수와 유사하지만, 매개변수는 배열로 받는것에 있어 차이가 있다.
- call: 객채를 바인딩 함과 동시에 호출을 한다.
- bind: 바인딩이된 함수를 반환하며, 한번더 호출시 함수를 실행한다.
'Programming > JavaScript' 카테고리의 다른 글
JavaScript - 실행 컨텍스트 (Execution Context) (0) | 2025.02.10 |
---|