this 개념
- 자신이 속한 객체, 자신이 생성할 인스턴스를 가리키는 식별자 (자기 참조 변수)
- this 바인딩은 함수 호출 방식에 따라 동적으로 결정된다.
- 자바스크립트 엔진이 암묵적으로 생성함
호출 방식에 따른 this 바인딩
1. 객체 리터럴 → 메서드를 호출한 객체를 가리킨다
const circle = {
radius: 5,
getDiameter() {
return 2 * this.radius;
}
}
console.log(circle.getDiameyer()); // 10
2. 생성자 함수 → 생성자 함수가 생성할 인스턴스를 가리킨다
function Circle(radius) {
this.radius = radius;
}
Circle.prototype.getDiameter = function() {
return 2 * this.radius;
}
const circle1 = new Circle(5);
console.log(circle1.getDiameter()); // 10
const circle2 = new Circle(100);
console.log(circle2.getDiameter()); // 200
3. 기타
- 전역 → 전역 객체(window)
- 일반 함수 → 전역 객체(window)
- strict mode 일반 함수 → undefined
// 1. 전역
console.log(this); // window
// 2. 일반 함수
function square(number) {
console.log(this); // window
return number * number;
}
square(2)
// 3. strict mode 에서의 일반 함수
'use strict';
function square2(number) {
console.log(this); // undefined
return number * number;
}
square2(2)
함수 호출 방식에 따른 this 바인딩
🚨 렉시컬 스코프와 this 바인딩은 결정 시기가 다르다.
- 렉시컬 스코프: 함수 정의가 평가되어 함수 객체가 생성되는 시점에 결정됨 (함수의 상위 스코프를 결정)
- this 바인딩: 함수 호출 시점에 결정됨 (this 바인딩을 결정)
1. 일반 함수 호출
- 일반적으로는 전역객체가 바인딩 된다.
- strict mode에서는 undefined가 바인딩 된다. (객체를 생성하지 않는 일반 함수에서는 this가 의미없기 때문)
- 어떠한 함수라도 일반 함수로 호출되면 this에 전역 객체가 바인딩 된다. (중첩 함수, 콜백 함수 포함)
var value = 1;
const obj = {
value: 100,
foo() {
console.log(this); // {value:100, foo:f}
// 메서드 내의 중첩 함수 정의
function bar() {
console.log(this); // window
console.log(this.value); // 1
}
// 중첩 함수 호출 -> 이 시점에 this 바인딩이 일어남 -> bar 내부의 this에는 전역객체 바인딩
bar();
setTimeout(function() {
console.log(this); // window
console.log(this.value); // 1
}, 100);
}
}
obj.foo();
2. 메서드 호출
- 메서드를 호출할 때 마침표(.) 연산자 앞에 기술한 객체가 바인딩 된다.
- 메서드를 소유한 객체가 아닌 메서드를 호출한 객체에 바인딩 된다.
const person = {
name: 'KIM',
// 메서드는 객체에 포함된 것이 아닌 독립적으로 존재하는 별도의 객체임!
getName() {
return this.name;
}
};
console.log(person.getName()); // KIM
3. 생성자 함수 호출
- 생성자 함수가 미래에 생성할 인스턴스가 바인딩 됨
- new 연산자로 호출해야 생성자 함수로 호출한 것! → 그냥 호출한다면 일반 함수 호출과 같음
function Circle(radius) {
this.radius = radius;
this.getDiameter = function() {
return 2 * this.radius;
}
}
const circle1 = new Circle(5);
const circle2 = new Circle(10);
console.log(circle1.getDiameter()); // 10
console.log(circle2.getDiameter()); // 20
const circle3 = Circle(15); // 일반 함수 호출
console.log(circle3); // undefined
4. apply/call/bind 메서드에 의한 간접 호출
- this로 사용할 객체와 인수 리스트를 인수로 전달받아 호출 → 첫번째 인수로 전달한 객체가 this가 됨
- apply, call 메서드는 함수를 호출하는 것!
- bind는 함수를 호출하지 않고 바인딩이 교체된 함수를 새롭게 생성하여 반환함
function getThisBinding() {
return this;
}
const thisArg = { a:1 };
console.log(getThisBinding()); // window
// apply는 두번째 인수 전달 시 배열로 묶어 전달
console.log(getThisBinding.apply(thisArg)); // {a:1}
// call는 두번째 인수 전달 시 쉼표로 구분한 리스트 형식으로 전달
console.log(getThisBinding.call(thisArg)); // {a:1}
this 바인딩을 일치 시키는 방법
1. Function.prototype.apply / call / bind
- this를 명시적으로 바인딩할 수 있는 메서드를 사용
var value = 1;
const obj = {
value: 100,
foo() {
setTimeout(function() {
console.log(this.value); // 100
}.bind(this), 100);
}
}
obj.foo();
2. 화살표 함수 사용
- 화살표 함수 내부의 this는 상위 스코프의 this를 가리킨다.
var value = 1;
const obj = {
value: 100,
foo() {
setTimeout(() => console.log(this.value), 100); // 100
}
}
obj.foo();
'FE > Javascript' 카테고리의 다른 글
[Javascript] 프로토타입 복습 (1) | 2025.07.29 |
---|---|
13. 모던 자바스크립트 Deep Dive(스코프) (0) | 2024.12.08 |
12. 모던 자바스크립트 Deep Dive(함수) (0) | 2024.12.07 |
11. 모던 자바스크립트 Deep Dive(원시 값과 객체의 비교) (0) | 2024.12.06 |
10. 모던 자바스크립트 Deep Dive (객체 리터럴) (0) | 2024.12.05 |