오늘은 항상 애매하게 알고있던 Javascript의 this에 대해 정확히 짚고 넘어가보려고 한다.
참고 - [코딩알려주는누나]개발자 면접 단골질문 자바스크립트 this
this란?
- this는 함수가 호출될 때 결정이 된다.
car라는 함수에서 this를 찍고 호출하여 값을 출력해보자.
const car = {
name: 'KIA',
getName: function () {
console.log("car get Name", this)
}
}
car.getName()
// 출력 결과
// car get Name { name: 'KIA', getName: [Function: getName] }
- car라는 객체가 getName 함수를 호출했기 때문에 car 객체가 this로 나타남
이번엔 car 함수를 담은 새로운 함수인 globalCar를 생성하여 새로 호출해보자
const car = {
name: 'KIA',
getName: function () {
console.log("car get Name", this)
}
}
// car.getName()
const globalCar = car.getName
globalCar()
// 출력 결과
// 영상에선 브라우저에서 console을 확인하기 때문에 window 객체가 나오지만
// 필자는 node환경을 사용하기 때문에 node의 global객체가 나오는 점 참고
// <ref *1> Object [global] {
// global: [Circular *1],
// queueMicrotask: [Function: queueMicrotask],
이 상황에선 부르는 객체없이 함수를 담은 값 자체를 글로벌에서 호출했기 때문에 this는 글로벌 환경 그 자체가 됨.
2번째 예제를 통해 확실히 알아보자
const car = {
name: 'KIA',
getName: function () {
console.log("car get Name", this)
}
}
const car2 = {
name: 'HYUNDAI',
getName: car.getName
}
car2.getName()
// 출력 결과
// car get Name { name: 'HYUNDAI', getName: [Function: getName] }
이를 통해 알 수 있는 점은 this를 부르는 객체에 따라 바뀐다는 것을 알 수 있다.
만약 html에 버튼을 생성해서 버튼을 누를 때 this가 포함된 함수를 호출한다면?
btn.addEventListener('click', car.getName)
// 출력 결과
// car get Name <button id="button">this</button>
버튼 태그 그 자체가 나와버리게 됨.
그렇다면 this를 내가 원하는 값으로 지정해주고 싶을 땐? → .bind(해당객체)
const car = {
name: 'KIA',
getName: function () {
console.log("car get Name", this)
}
}
const globalCar = car.getName
const car2 = {
name: 'HYUNDAI',
getName: car.getName
}
const bindGetName = car2.getName.bind(car)
bindGetName()
// 출력 결과
// { name: 'KIA', getName: [Function: getName] }
버튼 또한 위와 같은 방식으로 바인딩을 해준다면 원하는 객체를 가져올 수 있다.
const btn = document.getElementById('button')
btn.addEventListener("click", car.getName.bind(car))
this 연습 예제
const testCar = {
name: 'benz',
getName : function () {
console.log("getName", this.name)
const innerFunc = function () {
console.log("innerFunc", this.name)
}
innerFunc();
}
}
testCar.getName()
// 출력 결과
// getName benz
// innerFunc undefined
왜 이런 결과가 나왔는지 다시 알아보자
const testCar = {
name: 'benz',
getName : function () {
console.log("getName", this)
const innerFunc = function () {
console.log("innerFunc", this)
}
innerFunc();
}
}
testCar.getName()
// 출력 결과
// getName { name: 'benz', getName: [Function: getName] }
// innerFunc <ref *1> Object [global] { ...
this로만 찍어서 확인해보면
innerFunc()같은 경우에는 호출자가 없기 때문에 글로벌이 호출하게 되고,
testCar.getName()은 testCar 객체가 호출했기 때문에 정상적인 name이 나왔던 것이다.
만약 innerFunc의 this도 testCar의 this와 같게 하고 싶다면?
- .bind 사용
- 화살표 함수 사용
화살표 함수를 사용해서 같게 해보자
- 일반함수에서의 this와 화살표 함수에서의 this가 다르다.
- 화살표 함수에서의 this는 함수가 속해있는 곳의 상위 this를 계승 받는다.
const testCar = {
name: 'benz',
getName : function () {
console.log("getName", this)
const innerFunc = () => {
console.log("innerFunc", this)
}
innerFunc();
}
}
testCar.getName()
// 출력 결과
// getName { name: 'benz', getName: [Function: getName] }
// innerFunc { name: 'benz', getName: [Function: getName] }
this 연습 예제 2
리스트들 뒤에 n’살’ 이라고 붙이고 싶은데 function을 쓰면 상위 객체의 unit을 계승받지 못하므로 NaN이 출력 되게 된다.
const ageTest = {
unit:'살',
ageList:[10, 20, 30],
getAgeList:function () {
const result = this.ageList.map(function(age){
return age+this.unit;
})
console.log(result);
}
}
ageTest.getAgeList()
// 출력 결과
// [ NaN, NaN, NaN ]
해결 방법은 화살표 함수를 사용하는 것 (*화살표 함수는 바인딩을 제공하지 않는다.)
const ageTest = {
unit:'살',
ageList:[10, 20, 30],
getAgeList:function () {
const result = this.ageList.map((age)=>{
return age+this.unit;
})
console.log(result);
}
}
ageTest.getAgeList()
// 출력 결과
// [ '10살', '20살', '30살' ]
'Javascript & React' 카테고리의 다른 글
[Javascript] 자바스크립트 Closure에 대한 이해와 설명( + 예시 ) (0) | 2023.01.25 |
---|---|
[React] RTK(Redux Tool Kit)에 대해 알아보자 (0) | 2022.12.28 |
[Javascript] 일급 객체, Callback함수, 고차함수 (0) | 2022.12.23 |
[Javascript] Javascript에서 함수 호출 때 괄호의 유무? (0) | 2022.12.23 |
JavaScript의 주요 개념 정리(문법) (0) | 2022.04.26 |