두둥..!
마.참.내! this
에 대해 정리할 시간...🫠
예전에 공부할 때도 언제는 이해가 되다가 갑자기 또 꼬이는 개념이었다.
this
를 잘 정리해두어야 나중에 배울 클래스(Class)
로 생성한 인스턴스를 조금 더 쉽게 이해할 수 있기 때문에 확실히 정리해야한다!!
아좌좌 가보자고---!!!!
this
this
는 실행 컨텍스트가 생성될 때 결정된다. "this
를 묵는다", "bind한다" 라고도 한다.
즉 this
는 함수를 호출
할 때! 결정된다!고 정리할 수 있다.
🙄 실행 컨텍스트가 뭐였더라..
실행 컨텍스트 : 실행할 코드에 제공할 환경 정보를 모아놓은 객체!
이렇게 3가지가 있는데 this
는 세번째 ThisBindings
에 해당한다.
전역 공간에서 this
는 전역 객체
를 가리킨다. 따라서 이때의 this
를 확인해보면 브라우저에서는 windo
w가, node환경에서는 global
을 가리킨다.
함수 내부에서는 '호출 주체'에 따라 this
가 결정된다.
예시 코드를 보며 정리해보자
2-1) 함수 일 때 this
var func = function (x) {
console.log(this, x);
};
func(1); // Window or Global
func(1)
로 바로! 불러와진 경우인데 이럴 때는 호출 주체를 명시할 수 없어서 전역객체
를 의미한다.
2-2) 메서드 일 때 this
// 호출 주체를 명시할 수 있기 때문에 this는 해당 객체(obj)를 의미해요.
// obj는 곧 { method: f }를 의미하죠?
var obj = {
method: func,
};
obj.method(2); // { method: f } 2
여기서는 메소드 앞 .(온점)에 obj
라고 호출 주체를 명시할 수 있어 { method: f }
를 가리킨다.
⭐️ 함수 호출 vs 메서드 호출 구분 기준은 .
또는 [ ]
로 확인하자!
2-3) 메서드 내부의 this
var obj = {
methodA: function () { console.log(this) },
inner: {
methodB: function() { console.log(this) },
}
};
obj.methodA(); // this === obj
obj['methodA'](); // this === obj
obj.inner.methodB(); // this === obj.inner
obj.inner['methodB'](); // this === obj.inner
obj['inner'].methodB(); // this === obj.inner
obj['inner']['methodB'](); // this === obj.inner
조금 복잡해지긴 했지만 .
또는 [ ]
를 확인하면 this가 뭘 가리키는지 비교적 쉽게 알 수 있다.
위에서 배웠듯 함수로 호출하면 this
는 전역객체를 가리킨다.
이 내용을 까먹지말고! 함수 안에 있어도 함수가 '독립적으로' 호출되면 항!상! 전역객체를 가리킨다.
메서드 안에 있는 내부함수에서도 똑같이 함수로 호출되면 this
는 전역객체
를 의미한다.
var obj1 = {
outer: function() {
console.log(this); // (1)
var innerFunc = function() {
console.log(this); // (2), (3)
}
innerFunc();
var obj2 = {
innerMethod: innerFunc
};
obj2.innerMethod();
}
};
obj1.outer();
주석으로 달아놓은 번호의 this
를 찾아보자
(1): obj1
(2): 전역객체
(innerFunc가 바로 호출되었으므로)
(3): obj2
(innerMethod에 의해 실행된 innerFunc)
ES6에서 도입된 화살표 함수는 따로 알아두어야한다!
함수 내부에서 this
가 전역객체를 가리키는 문제때문에 도입되었으므로,
실행 컨텍스트를 생성할 때 화살표함수에서는 this
를 바인딩 과정 자체가 없다!
var obj = {
outer: function() {
console.log(this); // (1)
var innerFunc = () => {
console.log(this); // (2)
};
innerFunc();
}
}
obj.outer();
화살표함수가 쓰인 코드에서 this
를 찾아보면?
(1),(2) 모두 obj
를 가리킨다.
⭐️ 👩🏻💻 잠깐 지나가는 면접 Tip!
Q: 일반함수와 화살표함수의 가장 큰 차이점이 뭔가?
A: this binding의 여부임다. •̀.̫•́✧
🔍 콜백함수 : 어떠한 함수, 메서드의 인자(매개변수)로 넘겨주는 함수
나중에 콜백함수를 정리할 때도 계속 반복해서 쓸거지만 무조건 기억하기
"콜백함수도! 함수다!"
콜백함수 내부에서 this
는 콜백함수를 넘겨받은 함수(메서드)가 정한 규칙에 따라 값이 결정된다.
콜백함수도 함수이기 때문에 this
는 전역객체를 가리키지만, 넘겨받은 함수가 별도로 this
를 지정하면!! 그 대상을 참조한다.
// 1)
setTimeout(function () { console.log(this) }, 300);
// 2)
[1, 2, 3, 4, 5].forEach(function(x) {
console.log(this, x);
});
// 3)
// addListener 안에서의 this는 항상 호출한 주체의 element를 return하도록 설계되었음
// 따라서 this는 button을 의미함
document.body.innerHTML += '<button id="a">클릭</button>';
document.body.querySelector('#a').addEventListener('click', function(e) {
console.log(this, e);
});
1번과 2번은 별도로 this
한테 지정한게 없어서 전역객체를 가리키지만..!
3번의 경우 addEventListener
가 클릭되고 콜백함수를 호출하면 자신의 this
를 상속한다.
addEventListener
앞에 #a
가 버튼이니까 이 경우 this
는 버튼
을 가리킨다.
개념만 보면 쉬워보이고 이해가 되는 것 같지만 직접 짜보거나 조금만 복잡해 보이는 코드를 읽어보면 또 헷갈릴 것이다...
this
를 잘 활용해야 call, apply, bind도 잘 쓸 수 있고 클래스(Class)쓸 때도 엄청 중요하게 여겨지니까 호다닥 넘기지 말고 꼼꼼하게 이해하고 넘어가자!!