this는 JavaScript에서 함수가 호출될 때 결정되는 특별한 키워드이다.
JavaScript에서 this는 함수가 어떻게 호출되었는지에 따라 바인딩된다.
선언 위치가 아닌 호출 시점에 따라 결정되므로, 예상과 다른 동작이 발생하기 쉽다.
1. 호출 방식에 따라 달라지는 this
const obj = {
name: 'obj',
logThis: function () {
console.log(this.name);
}
};
obj.logThis(); // 'obj'
const extracted = obj.logThis;
extracted(); // undefined
const wrapper = { name: 'wrapper', call: obj.logThis };
wrapper.call(); // 'wrapper'
2. 예상과 다른 this 동작
const temperatureLogger = {
unit: "°C",
values: [23, 25, 27],
printTemperatures: function () {
const result = this.values.map(function (val) {
return val + this.unit;
});
console.log(result); // [NaN, NaN, NaN]
},
};
temperatureLogger.printTemperatures();
map 내부 콜백이 일반 함수로 실행되어 this는 전역 객체(window)를 가리킨다.
3. 호출 방식별 this 예시
메서드 호출
const fruit = {
name: "apple",
getName: function () {
console.log(this.name);
},
};
fruit.getName(); // apple
함수 분리
const fn = fruit.getName;
fn(); // undefined
다른 객체에 재할당
const fruit2 = {
name: "banana",
getName: fruit.getName,
};
fruit2.getName(); // banana
중첩 함수
const book = {
title: "JavaScript",
printTitle: function () {
console.log("outer:", this.title); // JavaScript
function inner() {
console.log("inner:", this); // Window
}
inner();
},
};
book.printTitle();
4. this 고정 방법: bind / call / apply
bind
function printName() {
console.log(this.name);
}
const fruit = { name: "apple" };
const boundFn = printName.bind(fruit);
boundFn(); // apple
bind()는 새로운 함수를 반환하며, 해당 함수가 호출될 때 this가 항상 지정한 객체를 참조하도록 만든다.
즉시 호출되지는 않고, 나중에 호출할 수 있도록 this가 '고정된' 버전을 반환한다.
❗ 화살표 함수에는 bind()를 사용해도 this가 바뀌지 않는다.
call / apply
call()과 apply()는 함수를 즉시 호출하면서 this를 특정 객체로 설정하고 싶을 때 사용한다.
이 둘의 차이는 인자를 전달하는 방식이다:
- call(thisArg, arg1, arg2, ...) → 인자를 나열
- apply(thisArg, [arg1, arg2, ...]) → 인자를 배열로 전달
❗ 화살표 함수는 call()이나 apply()를 사용해도 this를 변경할 수 없다.
예시 1
var obj = { a: "Custom" };
var a = "Global";
function whatsThis() {
return this.a;
}
whatsThis(); // "Global"
whatsThis.call(obj); // "Custom"
whatsThis.apply(obj); // "Custom"
예시 2
function add(c, d) {
return this.a + this.b + c + d;
}
var o = { a: 1, b: 3 };
add.call(o, 5, 7); // 16
add.apply(o, [10, 20]); // 34
⚠️ 비엄격 모드에서는 null이나 undefined를 넘기면 this는 전역 객체가 된다.
숫자나 문자열 같은 원시값은 해당 생성자 함수로 감싸진 객체로 변환된다.
function bar() {
console.log(Object.prototype.toString.call(this));
}
bar.call(7); // [object Number]
bar.call("foo"); // [object String]
bar.call(undefined);// [object global]
5. 화살표 함수에서의 this
화살표 함수는 자신만의 this를 가지지 않는다.
대신 선언된 위치의 상위 스코프에서 this를 가져온다.
이 특성 때문에 bind(), call(), apply()를 사용해도 화살표 함수의 this는 바뀌지 않는다.
즉, 화살표 함수에 this를 명시적으로 바인딩해도 효과가 없다는 점에 유의해야 한다.
function outer() {
this.name = "outer";
const inner = () => {
console.log(this.name); // "outer"
};
inner();
}
outer();
const obj = {
name: "arrow",
show: () => {
console.log(this.name);
},
};
obj.show(); // undefined
const bound = obj.show.bind({ name: 'bound' });
bound(); // 여전히 undefined
6. 생성자 함수 vs 일반 함수 호출
var name = 'global';
function Func() {
this.name = 'Func';
}
var a = Func();
console.log(name); // 'Func'
console.log(a); // undefined
var b = new Func();
console.log(b.name); // 'Func'
- new 없이 호출 → this는 전역 객체를 가리킴
- new와 함께 호출 → 새 객체가 생성되고 this에 바인딩됨
7. 이벤트 리스너에서의 this
<button id="btn">Click</button>
<script>
const button = document.getElementById("btn");
button.addEventListener("click", function () {
console.log(this); // <button>
});
button.addEventListener("click", () => {
console.log(this); // window
});
</script>
- 일반 함수 → this는 이벤트를 발생시킨 요소를 가리킨다 (이 예시에선 <button>)
- 화살표 함수 → this는 상위 스코프의 값을 그대로 참조하며, 일반적으로 window
💡 DOM 이벤트 처리기로 함수가 사용될 경우 this는 이벤트를 발생시킨 요소로 자동 설정된다.
하지만 addEventListener() 이외의 방법(예: element.onclick = ...)이나 구형 브라우저에서는 이러한 동작이 일관되지 않을 수 있다. 항상 명확한 동작을 원한다면 addEventListener() 사용이 권장된다.
8. 예제 해결 방법 정리
const temperatureLogger = {
unit: "°C",
values: [23, 25, 27],
printTemperatures: function () {
// 방법 1: bind 사용
const result1 = this.values.map(function (val) {
return val + this.unit;
}.bind(this));
// 방법 2: 화살표 함수 사용
const result2 = this.values.map(val => val + this.unit);
console.log(result1); // ["23°C", "25°C", "27°C"]
console.log(result2); // ["23°C", "25°C", "27°C"]
},
};
참고
'FE > JS' 카테고리의 다른 글
자바스크립트 - 클로저 (1) | 2025.05.19 |
---|---|
자바스크립트 실행 컨텍스트 (0) | 2025.05.19 |
자바스크립트 호이스팅 정리 (1) | 2025.05.18 |
null, undefined, undeclared, NaN (1) | 2025.05.17 |
JavaScript: var, let, const (0) | 2025.05.13 |