일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- react
- TypeScript
- java
- media query
- CSS
- react-router-dom
- Servlet
- JavaScript
- max-width
- 그럼에도불구하고
- github
- 그럼에도 불구하고
- 반응형 페이지
- 자바
- 자바문제풀이
- JS
- 프론트엔드
- node
- coding
- frontend
- node.js
- webpack
- @media
- cleancode
- redux
- git
- 코드업
- HTML
- 변수
- 코딩테스트
- Today
- Total
그럼에도 불구하고
[JavaScript] this에 대해 알아보자 본문
오늘은 this에 대해 기록해보고자 한다.
이론적인 부분에서 공부할 때 너무 어려운 부분이 많았다.
그래서 이해가 안되는 부분이 많았는데 부족할 수 있지만 이번 계기로 확실히 정리해 보자
결론부터 말하자면
1. this는 함수가 호출될 때 결정이 된다.
2. 화살표 함수에서의 this는 함수가 속해있는 곳의 상위 this를 계승받는다.
실습으로 내가 이해한 대로 적어봐야겠다.
ver_1
<script>
const car = {
name : 'KIA',
getName : function() {
console.log("car getName", this);
},
};
//car.getName(); // A.b
const globalCar = car.getName;
globalCar(); // b
</script>
car라는 객체는 name 값으로 "KIA"를 가지고 있다.
여기서 car.getName(); 으로 car라는 객체의 getName() 메서드를 호출했다.
this는 함수가 호출될 때 결정이 된다.
즉, car.getName();는 car가 getName()을 호출한 것이다.
이때 getName() 안에 있는 this는 자신을 호출한 객체를 가리킨다.
결과 :
ver_2
<script>
const car = {
name : 'KIA',
getName : function() {
console.log("car getName", this);
},
};
//car.getName(); // A.b
const globalCar = car.getName;
globalCar(); // b
</script>
globarCar();를 호출하면 어떤 값이 나올까?
this는 함수가 호출될 때 결정이 된다고 했다.
그렇다면 car.getName도 첫 번째 예시와 같은 값이 나올 것 같지만 그렇지 않다.
결과 :
뜬금없이 Window 내장 객체가 나온다.
이건 ver_1과 다르다.
ver_1의 경우는 car.getName();로 car가 getName()을 호출했지만,
ver_2의 경우는 car.getName()이라는 값을 globalCar라는 변수에 초기화한 것이다.
즉, const globalCar = car.getName;에서 globalCar가 car.getName(); 을 호출한 셈이다.
그렇기 때문에 전역변수로 선언된 globalCar에 맞춰 this는 Window 객체를 가리키는 것이다.
ver_3
<script>
const car = {
name : 'KIA',
getName : function() {
console.log("car getName", this);
},
};
const car2 = {
name :"hyundai",
getName : car.getName,
};
car2.getName();
</script>
car2라는 객체는 getName이라는 이름으로 car 객체의 getName 메서드를 호출하고 있다.
this는 함수가 호출될 때 결정이 된다고 했다.
car2가 getName()을 호출하고 있기 때문에 여기서 this는 car2를 말한다.
결과:
ver_4
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="button">click</button>
<script>
const car = {
name : 'KIA',
getName : function() {
console.log("car getName", this);
},
};
//car.getName(); // A.b
const btn = document.getElementById("button");
btn.addEventListener('click', car.getName);
</script>
</body>
</html>
btn이라는 변수는 button이란 id 선택자를 가진 button태그이다.
여기서 btn 즉, button을 클릭했을 때 car.getName의 this는 무엇을 가리킬까?
결과:
신기하게도 button 태그 자체를 가져와서 출력한다.
this는 함수가 호출될 때 결정이 된다고 했다.
btn.addEventListener('click', car.getName); 은 btn이라는 button을 클릭했을 때 발생하는 이벤트이다.
그 이벤트는 car.getName을 호출하며, 호출을 하는 대상은 btn이다.
그렇기 때문에 <button id="button"> click </button>을 출력하는 것이다.
ver_5
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="button">click</button>
<script>
const car = {
name : 'KIA',
getName : function() {
console.log("car getName", this);
},
};
//car.getName(); // A.b
const btn = document.getElementById("button");
btn.addEventListener('click', car.getName.bind(car));
</script>
</body>
</html>
ver_4와 바뀐 점은 btn.addEventListener('click', car.getName.bind(car)); 에서 bind()라는 함수가 호출된 것이다.
※ bind()
bind() 함수는 this의 값을 고정시키기 위한 함수이다.
즉, bind() 안에 들어갈 객체를 지정하면 this는 해당 객체를 가리키게 된다.
bind()는 this가 바인딩되는 객체만 변경하고 함수를 실행하지 않는다. 그 대신 변경된 새로운 함수를 반환한다.
결과:
원래 this의 주인인 car 객체 값을 출력한다.
ver_6
<script>
const car2 = {
name :"hyundai",
getName : car.getName,
};
const bindGetName = car2.getName.bind(car2);
bindGetName();
</script>
ver_2의 경우에서 bind() 함수만 추가된 것이다.
즉, bind(car2)가 없다면 Window 내장 객체가 출력되겠지만 bind(car2)로 this를 car2의 값으로 고정시켜 놓은 것이다.
const bindGetName = car2.getName.bind(car2);
결과:
ver_7
<script>
const testCar = {
name : "benz",
getName : function () {
console.log("getname", this);
const innerFunc = function() {
console.log("innerFunc", this);
};
innerFunc();
}
};
testCar.getName();
</script>
결과 값으로 두 번 호출될 값을 예측해 보자 ( 더보기 클릭하면 정답 나옵니다! )
첫 번째 console.log("getname", this);의 경우 무난하게 맞췄을 것 같다.
혹시 두 번째 console.log("innerFunc", this);의 this는 testCar가 호출했기 때문에 첫 번째 결과와 같은 결과를 예상했을 수도 있다. (내가 그랬다.)
여기서 중요하게 볼 점은 innerFunc();를 호출할 때.(닷)이 없다.
겉보기에는 testCar가 호출하는 것 같지만 ( . ) 이 없기 때문에 Window 객체가 호출한 것이다.
그렇다면 innerFunc();를 호출할 때의 this를 첫 번째 this랑 같은 값이 나오게 할 수는 없을까?
이건 당연히 안된다.
이것도 안된다.
그렇다면 어떻게 해야 할까?
ver_8
<script>
const testCar = {
name : "benz",
getName : function () {
console.log("getname", this);
const innerFunc = () => {
console.log("innerFunc", this);
};
innerFunc();
}
};
testCar.getName();
</script>
위처럼 화살표 함수를 사용하게 된다.
화살표 함수에서의 this는 함수가 속해있는 곳의 상위 this를 계승받는다.
참고로 화살표 함수는 bind 함수 (바인딩)을 제공하지 않는다.
ver_7과 ver_8을 내릴 수 있는 결론은
1. this를 쓰고 싶을 때는 일반 함수를 쓰자.
2. 외부 함수 안에 있는 내부 함수 같은 경우 같은 this를 쓴다면 화살표 함수를 사용하자.
ver_9
<script>
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();
</script>
내가 원하는 결과 값은 [ 10살, 20살, 30살 ]이지만 실제 출력 값은
이렇게 나오게 된다.
this.unit이 Window 내장 객체를 가리키고 있기 때문이다.
해결방법 1
<script>
const ageTest = {
unit : "살",
ageList : [10, 20, 30],
getAgeList : function() {
const result = this.ageList.map(function (age) {
return age + ageTest.bind;
});
console.log(result);
},
};
ageTest.getAgeList();
</script>
자기 자신을 호출한다.
해결 방법 2
<script>
const ageTest = {
unit : "살",
ageList : [10, 20, 30],
getAgeList : function() {
const result = this.ageList.map((age)=>{
return age + this.unit;
});
console.log(result);
},
};
</script>
ref:
'JavaScript > JavaScript basics' 카테고리의 다른 글
[JavaScript] FileReader 객체에 대해 알아보자 (0) | 2023.01.05 |
---|---|
[JavaScript] encodeURI / decodeURI란? (0) | 2023.01.03 |
[JavaScript] 문서 객체 모델 (DOM) (1) | 2022.12.30 |
[JavaScript] Symbol.Toprimitive란? (0) | 2022.12.29 |
[JavaScript] 자바스크립트 내장 객체 (0) | 2022.12.28 |