function normalFunc() {
console.log(this);
}
const arrowFunc = () => {
console.log(this);
}
실행 컨텍스트란 자바스크립트 코드가 실행되고 연산되는 범위를 나타내는 추상적인 개념으로 코드가 실행된다면 실행 컨텍스트 내부에서 작동하고 있는 것이라고 보면 됩니다.
기본적으로 코드가 실행되는 영역이며, 여기서 글로벌 객체인 Window 객체를 생성하며, this 를 글로벌 객체(Window 객체)로 설정해줍니다. 그래서 위에서 this 를 찍었을 때, Window 객체가 출력되었습니다.
각각의 함수가 가지는 실행 컨텍스트로, 함수가 호출될 때 해당 실행 컨텍스트 생성이 됩니다.
this가 바뀌는 시점
this는 기본적으로 Window 객체를 말합니다. 하지만 this 의 값이 바뀌는 경우가 있습니다. 때문에 this 값이 어떻게 바뀌고 있는지, 해당 this 가 무슨 값인지 알기 위해선 코드의 문맥을 살펴볼 필요가 있습니다.
객체의 메소드를 호출하는 경우
const obj = {
value: 6,
window: this,
func: function() {
return this;
},
arrowFun: () => {
return this;
},
};
console.log(myObj.myFunc()); // myObj 객체
console.log(myObj.myArrow()); // Window 객체
출력되는 this의 값이 다릅니다
함수를 어떤 객체의 메소드로 호출하면 this의 값은 그 객체를 사용합니다.
ES2015는 스스로의 this 바인딩을 제공하지 않는 화살표 함수를 추가했습니다.
-MDN web docs-
일반 함수는 해당 객체를 바인딩하여 this의 값을 변경하는 것이고, 화살표 함수는 상위 객체의 this를 그대로 이어받아 사용하는 것입니다.
생성자를 통해 객체를 생성하는 경우
function Progamer(name, age) {
this.name = name;
this.age = age;
}
// 생성자를 사용하지 않은 경우 - 단순 호출
const covy = Progamer('Facker', 28); // Facker 변수는 undefined
console.log(window.name, window.age); // Facker 28
// 생성자를 통한 객체 생성
const tony = new Progamer('Covy', 25);
console.log(tony.name, tony.age); // Covy 25 - this가 해당 객체에 바인딩됨
new 키워드를 통해 객체를 생성하면, this 가 해당 객체에 바인딩되어 해당 값을 읽게 되는 것입니다. ES6에 추가된 class를 사용하면 동일하게 작동합니다.
예외
Jquery, React 등에 일부 라이브러리에서 엘리먼트에 이벤트를 추가할 때, 콜백 함수에서 this 를 사용하면 값이 바뀌는 경우가 있습니다.
자바스크립트에서는 this 의 바인딩을 바꿀 수 있도록 해주는 메소드를 제공하는 데, 바로 apply , call , bind 입니다.
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 : 바인딩이된 함수를 반환하며, 한번더 호출시 함수를 실행한다.