당근 게임을 만들면서 아래의 코드를 실행했을 때 undefined
가 출력되었다.
this.field.addEventListener('click',this.onClick)
this.onClick은 할당이 되어있는 상태였는데 왜..?
이유는 click의 콜백으로 전달할 때 클래스의 정보는 안 넘어가기 때문이었다.
그래서 this를 공부하고 정리했다.
this는 함수가 호출될 때 결정된다.
function a(){
console.log(this); //window
}
a()
function b(){
function c(){
console.log(this)
}
c()
}
b();// window
var d = {
e:function(){
function f(){
console.log(this);
}
f(); // window
}
}
d.e() // d
function a(x,y,z){
console.log(this,x,y,z);
}
var b = {
bb:'bbb'
};
a.call(b,1,2,3) // {bb:"bbb"} 1 2 3
a.apply(b,[1,2,3]); // // {bb:"bbb"} 1 2 3
var c= a.bind(b);
c(1,2,3); // {bb:"bbb"} 1 2 3
var d = a.bind(b,1,2);
d(3) //{bb:"bbb"} 1 2 3
function Person(n,a){
this.name = n;
this.age = a;
}
var gisele1 = Person('나다',30);
console.log(window.name, window.age); // 나다, 30
var gisele2 = new Person('나다',30);
console.log(gisele); //Person{age:30,name:'나다'}
다시 맨 처음 문제로 돌아와서 콜백 함수에 class를 바인딩하기 위해서는 세 가지 방법이 있다.
// 1. bind 함수로 this바인딩 해주기
this.onClick = this.onClick.bind(this);
// 2. 콜백함수 내부에서 화살표 함수로 event 넘겨주기
this.field.addEventListener('click', (event) => this.onClick(event));
// 3. onClick 함수를 화살표 함수로 선언하기
this.field.addEventListener('click', this.onClick);
...
onClick = (event) => {
// arrow function은 자동으로 this바인딩
const target = event.target;
if (target.matches('.carrot')) {
target.remove();
playCarrot();
this.onItemClick && this.onItemClick('carrot');
} else if (target.matches('.bug')) {
this.onItemClick && this.onItemClick('bug');
playBug();
}
};