
this: 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수
this 바인딩
자바스크립트의 this는 함수가 호출되는 방식에 따라 this에 바인딩될 값, 즉 this 바인딩이 동적으로 결정됨
1. 전역 컨텍스트: 함수가 전역 범위에서 호출될 때, this는 전역 객체를 참조(브라우저에서는 window 객체가 전역 객체)
2. 함수 호출 시: 일반 함수 내에서 this는 호출되는 방법에 따라 동적으로 결정, 만약 함수가 메서드로서 호출되면, this는 그 메서드를 소유하는 객체를 참조
3. 메서드 내부: 객체의 메서드에서 this를 사용하면 this는 해당 메서드를 호출한 객체를 가리킴
4. 생성자 함수: 생성자 함수를 사용하여 객체를 생성할 때, this는 새로운 인스턴스를 참조
// 1.
console.log(this); // window
// 2-1.
function square(number) {
// 일반 함수 내부에서 this는 전역 객체 window를 가리킨다.
console.log(this); // window
return number*number;
}
// 2-2. (함수가 메서드로서 호출되는 경우)
const myObject = {
myMethod: function() {
console.log(this);
}
};
myObject.myMethod(); // myObject 객체를 출력
// 3.
const person = {
name: 'Lee',
getName() {
// 메서드 내부에서 this는 메서드를 호출한 객체를 가리킨다.
console.log(this); // {name: "Lee", getName: f}
return this.name;
}
};
// 4.
function Person(name) {
this.name = name;
// 생성자 함수 내부에서 this는 생성자 함수가 생성할 인스턴스를 가리킨다.
console.log(this); // Person {name: "Lee"}
}
const me = new Person('Lee');
📌 렉시컬 스코프: 함수의 상위 스코프를 결정하는 방식
함수 호출 방식
1. 일반 함수 호출
- 기본적으로 this에는 전역 객체가 바인딩됨(window)
- 일반 함수로 호출시 함수 내부의 this에는 전역 객체가 바인딩됨(window)
- strict mode가 적용된 일반 함수 내부의 this에는 undefined가 바인딩됨
- this는 객체의 프로퍼티나 메서드를 참조하기 위한 자기 참조 변수이므로 객체를 생성하지 않는 일반 함수에서 this는 의미가 없음
콜백 함수가 일반 함수로 호출된다면 콜백 함수 내부의 this에도 전역 객체가 바인딩됨
var value = 1;
const obj = {
value: 100,
foo() {
console.log("foo's this: ", this); // {value: 100, foo: f}
// 콜백 함수 내부의 this에는 전역 객체가 바인딩됨
setTimeout(function() {
console.log("callbak's this: ", this); // window
console.log("callbak's this.value: ", this.value); // 1
}, 100);
}
};
obj.foo()
중첩 함수나 콜백 함수의 this 바인딩을 메서드의 this 바인딩과 일치시키기 위한 방법
1) this 바인딩을 변수 that에 할당
var value = 1;
const obj = {
value: 100,
foo() {
const that = this;
setTimeout(function() {
console.log(that.value); // 100
}, 100);
}
};
obj.foo()
2) this를 명시적으로 바인딩할 수 있는 메서드 사용(apply, call, bind)
var value = 1;
const obj = {
value: 100,
foo() {
setTimeout(function() {
console.log(this.value); // 100
}.bind(this), 100);
}
};
obj.foo()
3) 화살표 함수 사용
var value = 1;
const obj = {
value: 100,
foo() {
setTimeout(() => console.log(this.value), 100); // 100
}
};
obj.foo()
const person = {
name: 'Lee',
getName() {
return this.name;
}
};
const anotherPerson = {
name: 'Kim'
}
anotherPerson.getName = person.getName;
console.log(anotherPerson.getName()); // Kim
console.log(person.getName()); // Lee
function Circle(radius) {
this.radius = radius;
this.getDiameter = function () {
return 2 * this.radius;
};
}
const circle1 = new Circle(5);
const circle2 = new Circle(10);
const circle3 = Circle(15);
console.log(circle1.getDiameter); // 10
console.log(circle2.getDiameter); // 20
console.log(circle3); // undefined
const thisArg = {a:1};
console.log(getThisBinding.apply(thisArg)); // {a:1}
console.log(getThisBinding.call(thisArg)); // {a:1}
const thisArg = {a:1};
console.log(getThisBinding.bind(thisArg)); // getThisBinding
// bind 메서드는 함수를 호출하지 않기 때문에 함수를 명시적으로 호출해야함
console.log(getThisBinding.bind(thisArg)()); // {a:1}
bind 메서드를 사용하여 콜백 함수의 this 불일치 문제를 해결하는 예제
// setTimeout이 일반 함수로 호출되었기 때문에 this는 전역 객체 window를 가리킴
const person = {
name: 'Lee',
foo (callback) {
setTimeout(callback, 100);
}
};
person.foo(function () {
console.log(this.name); // '' -> window.name
});
// bind 사용
const person = {
name: 'Lee',
foo (callback) {
setTimeout(callback.bind(this), 100);
}
};
person.foo(function () {
console.log(this.name); // 'Lee' -> person.name
}