자바 개발자로서 가장 당황스러운 부분이 this이다.
자바스크립트의 this는 다른 언어와 다르게 작동한다.
MDN에 따르면 this는 호출한 방법에 의해 결정된다.(MDN)
즉 대부분의 호출한 객체가 this가 된다(예외 존재).
- 일반 함수에서의 this는 호출 위치에서 정의
- 화살표 함수의 this는 자신이 선언된 함수(렉시컬) 범위에서 정의
- 렉시컬(Lexical)이란 함수가 동작할 수 있는 유효한 범위. 즉 함수의 범위
호출한 객체에 따라 this가 변경됨에 따라 런타임시 버그를 발생시킬 요소가 다분함.(요즘 같은 불변객체에 대한 지향점을 갖는 추세에서는 곤란한 문제)
ES5에서 이문제를 해결하기 위해 bind 메소드 제공
function printCar(){
console.log(this)
}
let superCar={
name : '슈퍼카'
}
let printSuperCar = printCar.bind(superCar)
printSuperCar() // => 슈퍼카
let thisTest={
name : 'jjryu'
printName: function(){
setTimeout(function(){
console.log(this) // 여기서 this는 윈도우
}.bind(this),1000); // 여기서 this를 현재 객체(jjryu)로 binding
}
}
코드를 리팩토링하여 function으로 빼면
let thisTest={
name : 'jjryu'
printName: function(){
function printThis(){
console.log(this);
};
setTimeout(printThis.bind(this),1000); // 여기서 this를 현재 객체(jjryu)로 binding
}
}
화살표 함수는 자신을 포함하는 외부 함수범위(렉시컬)에 의해 this가 결정된다.
Exam 01을 화살표 함수로 변경하면
let thisTest={
name : 'jjryu'
printName: function(){ // <= 여기가 외부함수 렉시컬
setTimeout(()=>{ // <= 자신의 scope
console.log(this)
},1000); // 여기서 this를 현재 객체(jjryu)로 binding
}
}
this 키워드가 있는 함수 정의시
let thisTest={
name : 'jjryu'
printNameArrow: ()=>{
console.log(this); // 화살표함수의 외부 scope이므로 window
}
printNmeFunction: function(){
console.log(this) // 자기자신
}
}
thisTest.printNameArrow();
thisTest.printNmeFunction();
btn.addEventListener('click',()=>{
console.log(this) // 여기서 this는 window
});
btn.addEventListener('click',function(){
console.log(this) // 여기서 this는 btn
})
bind는 한번만 사용 가능.
this는 너무 헷깔려..