2025.03.12 - [Frontend/JS] - 화살표 함수 & 비동기 처리 에서 간략하게 화살표 함수를 설명했다.
화살표 함수에서 this
키워드를 사용하는 방법을 작성하려 한다.
JS의 this
화살표 함수와 전통적인 함수는 서로 다른 this
값이 바인딩될 수 있다.
JS에서의 this는 메서드, 함수가 호출될 때마다 현재 호출중인 메서드를 보유한 객체가 this로 연결됨
만일, 현재 호출 중인 메서드를 보유한 객체가 없다면, 전역 객체 (Global Obj, window)가 연결된다.
let obj = { result: 0 };
obj.add = function (x, y) {
this.result = x + y;
};
obj.add(3, 4);
console.log(obj); // { result: 7, add: [Function (anonymous)] }
obj.add(3,4)
에서 add 메서드가 호출될 때, 이 메서드를 보유한 객체는 obj
임
따라서 3행의 this는 obj가 되므로 result에 7이 저장됨.
let obj = { result: 0 };
obj.add = function (x, y) {
this.result = x + y;
};
let add2 = obj.add;
add2(3,4)
console.log(obj); //{ result: 0, add: [Function (anonymous)] }
let add2 = obj.add
에서 addㅇ 메서드의 메모리주소가 add2로 복사된다.
따라서 obj.add와 add2는 같은 주소를 참조하는 동일한 함수
add2는 특정 객체의 메소드가 아니므로, 전역 객체 this로 연결된다.
this 바인딩
JS에서 함수, 메서드를 호출할 때 직접 연결할 THIS를 저장하고 싶다면, 아래의 함수 수준의 메서드를 이용할 수 있다.
bind() | 지정한 객체를 this로 미리 연결한 (binding) 새로운 함수 리턴 |
apply(), call() | 지정한 객체를 this로 연결한 후, 함수 직접 호출 |
let sum = function (x, y) {
this.result = x + y;
};
let res = {};
sum.apply(res, [3, 4]);
console.log(res); // {result: 7}
sum.call(res, 3, 5);
console.log(res); // {result: 8}
sum = sum.bind(res);
sum(3, 8);
console.log(res); // {result: 11}
bind()
메서드는 인자로 전달한 res를 this로 강제 지정하여 만든 새로운 함수를 리턴
새로운 함수의 메모리 주소가 다시 sum 변수에 재할당 되므로 특정 객체의 메서드 형태로 호출하지 않아도 this는 res임
화살표 함수의 this
전통적인 함수와 화살표 함수에서의 this 차이점을 알아보려면 함수가 중첩되는 상황을 살펴봐야 함.
// 중첩 함수에서의 this
let obj = { result: 0 };
obj.add = function (x, y) {
function inner() {
this.result = x + y;
}
inner();
};
obj.add(3, 4);
console.log(obj); // { result: 0, add: [Function (anonymous)] }
console.log(result); // 7
inner()
가 특정 객체의 메서드 형태가 아니므로 this는 전역객체를 가리킴. (window)
우리가 바라는 건 inner 함수의 this가 obj 객체를 가리키도록 하는 것이므로 앞서 배운 bind를 사용하자.
// 중첩 함수에서의 this
let obj = { result: 0 };
obj.add = function (x, y) {
function inner() {
this.result = x + y;
}
inner = inner.bind(obj);
inner();
};
obj.add(3, 4);
console.log(obj); // { result: 7, add: [Function (anonymous)] }
원하는 결과값은 얻었으나, 자연스러운 코드는 아님
이와 같은 상황에서는 아래와 같이 화살표 함수
를 사용하면 됨
let obj = { result: 0 };
obj.add = function (x, y) {
const inner = () => {
this.result = x + y;
};
inner();
};
obj.add(3, 4);
console.log(obj); // { result: 7, add: [Function (anonymous)] }
화살표 함수
는 함수가 정의되는 유효 범위의 this를 자신의 유효범위의 this로 연결하기 때문에
직접 binding 해주지 않아도 된다.
화살표 함수를 피해야 하는 경우
top-level에서 사용하는 경우
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<button>확인</button>
<script>
const button = document.querySelector('button');
// top-level에서 화살표 함수를 사용하는 경우
button.addEventListener('click', () => {
console.log(this); // window 객체
});
</script>
</body>
</html>
객체 리터럴의 메서드 정의에서 사용하는 경우
const person1 = {
age: 10,
grow: function () {
this.age++;
console.log(this.age);
},
};
person1.grow(); // 11
const person2 = {
age: 10,
grow: () => {
this.age++; // 여기서는 global 객체를 가리킴
console.log(this.age);
},
};
person2.grow(); //NaN
화살표 함수는 자신만의 this
를 가지지 않고, 선언될 때의 상위 스코프의 this를 따름
그런데 객체 리터럴 person2
는 this를 제공하는 실행 컨텍스트가 아님.
📌 화살표 함수는 어디에서 실행됐는지가 아니라, 어디에서 선언됐는지 기준으로 this를 결정함