자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수.
this를 통해 자신이 속한 객체 또는 자신이 생성할 인스턴스의 프로퍼티나 메서드를 참조할 수 있다.
this는 자바스크립트 엔진에 의해 암묵적으로 생성되며, 코드 어디서든 참조할 수 있다.
const circle = {
// 프로퍼티: 객체 고유의 상태 데이터
radius: 5,
// 메서드: 상태 데이터를 참조하고 조작하는 동작
getDiameter() {
// this는 메서드를 호출한 객체를 가리킨다.
return 2 * this.radius;
}
};
console.log(circle.getDiameter()); // 10
자바스크립트의 this는 함수가 호출되는 방식에 따라 this에 바인딩될 값, 즉 this 바인딩이 동적으로 결정된다. 또한 strict mode(엄격 모드) 역시 this 바인딩에 영향을 준다.
// this는 어디서든지 참조 가능하다.
// 전역에서 this는 전역 객체 window를 가리킨다.
console.log(this); // window
function square(number) {
// 일반 함수 내부에서 this는 전역 객체 window를 가리킨다.
console.log(this); // window
return number * number;
}
square(2); // 4
const person = {
name: 'Lee',
getName() {
// 메서드 내부에서 this는 메서드를 호출한 객체를 가리킨다.
console.log(this); // {name: "Lee", getName: f}
return this.name;
}
};
console.log(person.getName()); // Lee
this 바인딩(this에 바인딩 될 값)은 함수 호출 방식, 즉 함수가 어떻게 호출되었는지에 따라 동적으로 결정된다.
기본적으로 this에는 전역 객체가 바인딩된다.
function foo() {
console.log("foo's tihs: ", this); // window
function bar() {
console.log("bar's this: ", this); // window
}
bar();
}
foo();
메서드 내에서 정의한 중첩 함수도 일반 함수로 호출되면 중첩 함수 내부의 this에는 전역 객체가 바인딩된다.
const obj = {
value: 100,
foo() {
console.log("foo's this: ", this); // {value: 100, foo: f}
console.log("foo's this.value: ", this.value); // 1
// 메서드 내에서 정의한 중첩 함수
function bar() {
console.log("bar's this: ", this); // window
}
bar();
}
};
obj.foo();
일반 함수로 호출된 모든 함수(중첩 함수, 콜백 함수 포함) 내부의 this에는 전역 객체가 바인딩된다.
해결법
var value = 1; // window.value: 1
const obj = {
value: 100,
foo() {
// 콜백 함수에 명시적으로 this를 바인딩한다.
setTimeout(function() {
console.log(this.value); // 100
}.bind(this), 100);
}
};
obj.foo();
const person = {
name: 'Lee',
getName() {
// 메서드 내부의 this는 메서드를 호출한 객체에 바인딩된다.
return this.name;
}
};
// 메서드 getName을 호출한 객체는 person이다.
console.log(person.getName()); // Lee
const anotherPerson = {
name: 'Kim'
};
// getName 메서드를 anotherPerson 객체의 메서드로 할당
anotherPerson.getName = person.getName;
// getName 메서드를 호출한 객체는 anotherPerson이다.
console.log(anotherPerson.getName()); // Kim
// getName 메서드를 변수에 할당
const getName = person.getName;
// getName 메서드를 일반 함수로 호출
console.log(getName()); // ''
// 일반 함수로 호출된 getName 함수 내부의 this.name은 브라우저 환경에서 window.name과 같다.
생성자 함수 내부의 this에는 생성자 함수가 (미래에) 생성할 인스턴스가 바인딩된다.
// 생성자 함수
function Circle(radius) {
// 생성자 함수 내부의 this는 생성자 함수가 생성할 인스턴스를 가리킨다.
this.radius = radius;
this.getDiameter = function () {
return 2 * this.radius;
};
}
// 반지름이 5인 Circle 객체를 생성
const circle1 = new Circle(5);
// 반지름이 10인 Circle 객체를 생성
const circle2 = new Circle(10);
console.log(circle1.getDiameter()); // 10
console.log(circle2.getdiameter()); // 20
// new 연산자와 함께 호출하지 않으면 생성자 함수로 동작하지 않는다. 즉, 일반적인 함수의 호출이다.
const circle3 = Circle(15);
// 일반 함수로 호출된 Circle에는 반환문이 없으므로 암묵적으로 undefined를 반환한다.
console.log(circle3); // undefined
// 일반 함수로 호출된 Circle 내부의 this는 전역 객체를 가리킨다.
console.log(radius); // 15
function getThisBinding() {
return this;
}
// this로 사용할 객체
const thisArg = { a: 1 };
console.log(getThisBinding()); // window
// getThisBinding 함수를 호출하면서 인수로 전달한 객체를 getThisBinding 함수의 this에 바인딩한다.
console.log(getThisBinding.apply(thisArg)); // {a: 1}
console.log(getThisBinding.call(thisArg)); // {a: 1}
// apply 메서드는 호출할 함수의 인수를 배열로 묶어 전달한다.
console.log(getThisBinding.apply(thisArg, [1, 2, 3]));
// Arguments(3) [1, 2, 3, callee: f, Symbol(Symbol.iterator): f]
// {a: 1}
// call 메서드는 호출할 함수의 인수를 리스트 형식으로 전달한다.
console.log(getThisBinding.call(thisArg, 1, 2, 3));
bind 메서드는 apply와 call과 달리 함수를 호출하지 않는다. 다만 첫 번째 인수로 전달한 값으로 this 바인딩이 교체된 함수를 새롭게 생성해 반환한다.
function getThisBinding() {
return this;
}
// this로 사용할 객체
const thisArg = { a: 1 };
// bind 메서드는 첫 번째 인수로 전달한 thisArg로 this 바인딩이 교체된
// getThisBinding 함수를 새롭게 생성해 반환한다.
console.log(getThisBinding.bind(this.Arg)); // getThisBinding
// bind 메서드는 함수를 호출하지는 않으므로 명시적으로 호출해야 한다.
console.log(getThisBinding.bind(thisAr)()); // {a: 1}
this는 '일반 함수'와 '화살표 함수'에 따라 다르게 정의된다.
일반 함수는 호출 위치에서 정의되고,
화살표 함수는 this가 자신이 선언된 렉시컬(함수) 범위에서 정의된다.
let newC
let newD
// 객체 리터럴 선언!
const literal = {
a: 1,
b: 2,
// 일반 함수는 호출 위치에서 따라 this 정의!
c: function () {
console.log(this.a)
},
// 화살표 함수는 this가 자신이 선언된 렉시컬(함수) 범위에서 this 정의!
d: () => {
console.log(this.a)
}
}
literal.c() // 1
literal.d() // undefined
newC = literal.c
newD = literal.d
newC() // undefined
newD() // undefined
newC.call(literal) // 1
newD.call(literal) // undefined
오,, this 심화 예시코드까지 잘 정리해주셔서 화살표 함수와 일반함수 차이점에 대해 더 잘 이해할 수 있었어요!!! ㅎㅅㅎ