JavaScript에는 this라는 특별한 키워드가 있다.
다른 객체지향 언어에서의 this는 보통 클래스로 생성한 인스턴스 객체를 의미하고, 클래스에서만 사용할 수 있다. 하지만, JavaScript에서는 어디서든 this를 사용할 수 있고, 상황에 따라 this가 달라지기 때문에 많은 혼란을 준다.
this는 어떤 실행 컨텍스트가 생성될 때, 실행 컨텍스트의 환경 객체를 구성하는 3가지 요소 중 하나이다.
JavaScript에서 함수를 호출할 때 실행 컨텍스트가 생성되기 때문에 함수를 호출할 때 this가 결정된다고 할 수 있다.
실행 컨텍스트 - 참고
https://velog.io/@juwon98/JavaScript-execution-context
일반적인(this를 명시적으로 바인딩하지 않은) 경우, 아래와 같은 규칙에 따라 this가 결정된다.
console.log(this); // window
var obj = {
method: function() {
console.log(this);
}
};
obj.method(); // obj
function f1() {
console.log(this);
}
f1(); // window
메서드의 내부함수
var obj = {
outerF: function() {
console.log(this);
function innerF() {
console.log(this);
}
innerF(); // window
}
};
obj.outerF(); // obj
ES6에서 this를 바인딩하지 않는 화살표 함수가 등장했다.
화살표 함수 내부에는 this가 존재하지 않기 때문에, 스코프체이닝에 의해 가장 가까운 this를 찾는다.var obj = { outerF: function() { console.log(this); var innerF = () => { console.log(this); }; innerF(); } }; obj.outerF(); // obj obj추가 예시
var obj = { F: () => { console.log(this); } }; obj.F(); // window
setTimeout(function() {
console.log(this); // window
}, 1000);
/* setTimeout의 콜백함수는 this가 정의되지 않음 */
document.body.innerHTML += '<button id="btn" type="button">버튼</button>';
var btn = document.getElementById('btn');
btn.addEventListener('click', function(e) {
console.log(this, e); // btn, Event
});
/* addEventListener의 콜백함수는 this가 btn */
var Food = function(name, price) {
this.eatable = true;
this.name = name;
this.price = price;
}
var apple = new Food('사과', 3000);
var chocolate = new Food('초콜릿', 1500);
console.log(apple, chocolate);
/* 결과
Food {eatable: true, name: '사과', price: 3000}
Food {eatable: true, name: '초콜릿', price: 1500}
*/
function func(a, b, c) {
console.log(this, a, b, c);
}
func.call({x:'test'}, 1, 2, 3); // {x:'test'} 1 2 3
func.apply({x:'test'}, [1, 2, 3]); // {x:'test'} 1 2 3
function func(a, b, c) {
console.log(this, a, b, c);
}
var newFunc = func.bind({x:'new'});
newFunc(1,2,3); // {x:'new'} 1 2 3
var obj = {
sum: 0,
add: function() {
[1,2,3,4].forEach(function(item) {
this.sum += item;
},this); // add 메서드의 this(obj)를 전달
}
}
obj.add();
console.log(obj.sum); // 10