개발을 진행하다보면 this라는 키워드를 사용하면서 정확하게 이해를 하지 못하면서 사용하고 있었습니다.
이번 글로 한번 기초를 밟아보겠습니다.
F12나 Ctrl(=Command) + shift + c 를 눌러서
브라우저 콘솔에 일단 this를 찍어봅시다
> this
> Window {
0: Window, 1: Window, 2: global, window: Window,
self: Window, document: document, name: '', location: Location, … }
그냥 this를 입력했을때 Window객체가 나옵니다.
Window객체는 일반적으로 브라우저의 요소와 자바스크립트 엔진과 관련된 모든 정보를 포함하고 있는 객체입니다.
그렇지만 단순히 this = Window 객체인건 아닙니다.
우선 실행 컨텍스트 라는걸 알아야 합니다.
실행컨텍스트란 자바스크립트 코드가 실행되고 연산되는 범위를 나타내는 추상적인 개념입니다.
좀 더 쉽게 말하자면 실행 컨텍스트는 실행 가능한 코드가 실행되기 위해 필요한 환경 이라고 말할 수 있습니다.
여기서 말하는 실행 가능한 코드는 다음 세가지가 있습니다.
일반적으로 실행 가능한 코드는 전역코드와 함수코드입니다.
메인 주제가 this이니 전역(Global)과 함수(Function)의 실행 컨텍스트를 간단하게 설명하겠습니다.
기본적으로 코드가 실행되는 영역이며, 여기서 글로벌 객체인 Window객체를 생성하며, this를 글로벌 객체(Window객체)로 설정해줍니다.
그래서 아까 브라우저 상에 this
를 찍었을 때, Window객체가 출력 된것입니다.
각각의 함수가 가지는 실행 컨텍스트로, 함수가 호출될 때 해당 실행 컨텍스트가 생성됩니다.
function foo() {
console.log('foo')
} //Funtioncal Execution Context
function boo() {
const booVar = 8;
const printVar = (value) => console.log(value); //Funtioncal Execution Context
console.log('boo');
foo();
printVar(booVar);
}//Funtioncal Execution Context
const myNumber = 10;
boo();
/*Output*/
/*
//boo
//foo
//8
*/
this는 기본적으로 Window객체를 말합니다(Node.js는 Global 객체)
하지만 this의 값이 바뀌는 경우가 있습니다. 때문에 this 값이 어떻게 바뀌고 있는지,
해당 this가 무슨값인지 알기 위해선 코드의 문맥을 살펴볼 필요가 있습니다.
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 객체
Regular Function과 Arrow Function에 따라 this 의 값이 바뀌었습니다.
MDN에서는 아래와 같이 설명하고 있습니다.
— 함수를 어떤 객체의 메소드로 호출하면 this의 값은 그 객체를 사용합니다.
— ES2015는 스스로의 this 바인딩을 제공하지 않는 화살표 함수를 추가했습니다.
-MDN web docs-
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this
function
키워드는 해당 객체를 바인딩하여 this
의 값을 변경 하는 것이고,
() ⇒ {}
는 상위 객체의 this를 그대로 이어받아 사용하는 것입니다.
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
를 사용하면 동일하게 작동하는 것을 볼 수 있습니다.
Jquery, React등에 일부 라이브러리에서 엘리먼트에 이벤트를 추가할 때,
콜백함수에서 this
를 사용하면 값이 바뀌는 경우가 있습니다.
//Jquery
#('div').on('click', function() {
console.log(this) // <div>
function normalFunc(){
console.log(this); //Window 객체
}
const arrowFunc = () => {
console.log(this); // <div>
}
});
위 코드 처럼 라이브러리 상에서 this를 바인딩 해주는 경우가 있기도 하니
this
를 사용할 때는 해당 라이브러리의 docs를 찾아보는것도 중요합니다.
(특히 Vue!!!! Vue는 stackOverflow나 공식문서를 적극적으로 봐야한다)
사실 this
는 이 3개를 이해하기 위한 발판입니다.
자바스크립트에서는 this
를 자유자제로 바꿀 수 있도록 해주는 메소드를 제공하는데,
바로 apply, call, bind 입니다.
ES5는 함수를 어떻게 호출했는지 상관하지 않고 this값을 설정할 수 있는 bind메서드를 도입했습니다.
-MDN web docs- https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this
const Tome = {
age: 25,
gender: 'man',
};
function printProfile(name) {
console.log(name, this.age, this.gender);
}
printProfile.call(Tom, 'Tom'); // Tom 25 man
printProfile.apply(Tom, ['Tom']); // Tom 25 man
printProfile.bind(Tom, 'Tom').call(); // Tom 25 man
call
함수와 유사하지만, 매개변수는 배열로 받는것에 있어 차이가 있습니다.라이브러리나 프레임워크에 따라 쓰임세가 유동적으로 변하기 때문에 바닐라 JS를 쓰는게 아닌이상 약간의 차이를 감안하고 사용을 해야합니다.
개발을 하면 할수록 중급단계에서 사용빈도수가 높아지고 더 나아가 라이브러리 및 모듈 제작을 할때 적재적소로 활용될수 있으니 확실하게 개념을 짚고 넘어가는게 좋은것같습니다.