본문 바로가기
JavaScript

이벤트 (3)

by oncerun 2022. 3. 16.
반응형

 

 

이벤트 핸들러 내부 this

 

이벤트 핸들러 어트리뷰트 방식

<button onclick="handleClick()"></button>

 

이벤트 핸들러 어트리뷰트의 값으로 지정한 문자열은 사실 암묵적으로 생성되는 이벤트 핸들러의 문이라고 했다. 따라서 handleClick 함수는 이벤트 핸들러에 의해 일반 함수로 호출된다.

funciton onclick(){
	handleClick();
}

 

일반 함수의 호출의 내부 this는 전역 객체 window를 가리킨다. 다만 이벤트 핸들러를 호출할 때 인수로 전달한 this는 이벤트를 바인딩한 DOM 요소를 가리킨다.

 

 

이벤트 핸들러 프로퍼티 방식과 addEventListener 메서드 방식

 

두 방식 모두 이벤트 핸들러 내부의 this는 이벤트를 바인딩한 DOM 요소를 가리킨다. 

즉 이벤트 핸들러 내부의 this는 이벤트 객체의 currentTarget 프로퍼티와 같다.

 

const $button1 = document.querySelector('btn1');
const $button2 = document.querySelector('btn2');


//이벤트 핸들러 프로퍼티 방식
$button1.onclick = function (e) {
	console.log(this === e.currentTarget) //true;
};


$button2.addEventListener('click', function (e) {

	console.log(this === e.currentTarget); //true
});

 

화살표 함수는 함수 자체의 this, arguments, super, new.target 바인딩을 갖지 않기 때문에 화살표 함수로 정의한 이벤트 핸들러 내부의 this는 상위 스코프 this를 가리킨다. 

 

만약 클래스에서 이벤트 핸들러를 바인딩하는 경우 this에 주의해야 한다. 

 

class App{

	constructor(){
    	this.$button = document.querySelector('btn');
        
        this.$button.onclick = this.increase;
    }
    
    increase(){
    	this.$button.textContent = 'hi';
        //TypeError 
    }
}

 

increase 내부의 this는 DOM 요소인 (this.$button)를 가리킨다. 클래스가 생성할 인스턴스를 가리키지 않는다. 

따라서 increase 내부의 this.$button은 this.$button.$button과 같아 에러를 발생시킨다. 

 

이 경우 increase 메서드를 이벤트 핸들러로 바인딩할 때 bind 메서드를 사용해 this를 전달하여 increase 메서드 내부의 this가 클래스가 생성할 인스턴스를 가리키도록 해야 한다.

 

또는 클래스 필드에 할당한 화살표 함수를 이벤트 핸들러로 등록해 이벤트 핸들러 내부의 this가 인스턴스를 가리키게 할 수 있다.

class App{

	constructor(){
    	this.$button = document.querySelector('btn');
        
        this.$button.onclick = this.increase;
    }
    
    increase = () => this.$button.textContent = 'hi';
    
}

 

 

이벤트 핸들러에 인수를 전달하려고 한다. 이벤트 핸들러 어트리뷰트 방식은 함수 호출 문을 사용하기 때문에 

인수를 쉽게 전달할 수 있다. 

( 이 과정에서 작은따옴표, 큰따옴표가 들어간 인수를 jsp에서 넣고 클라이언트에게 전달할 경우.. 문법이 박살 난다. 조심)

 

다만 이벤트 핸들러 프로퍼티 방식과 addEventListener 메서드 방식의 경우 이벤트 핸들러를 브라우저가 호출하기 때문에 함수 자체를 등록해야 한다. 따라서 인수를 전달할 수 없는데 그 방법이 없는 것은 아니다.

 

1. 이벤트 핸들러 내부에서 함수 호출

const MIN_NAME_LENGTH = 5;

const checkNameLength = min => {
	console.log(min);
}

$input.onblur = () => {
	checkNameLength(MIN_NAME_LENGTH);
};

 

2. 이벤트 함수를 반환하는 고차 함수

const MIN_NAME_LENGTH = 5;

const checkNameLength = min => e => {
	console.log(min);
}

$input.onblur = checkNameLength(MIN_NAME_LENGTH);
반응형

'JavaScript' 카테고리의 다른 글

모듈  (0) 2022.03.26
Generator, async/await  (0) 2022.03.22
이벤트 (2)  (0) 2022.03.16
이벤트 (1)  (0) 2022.03.15
구조 분해 할당  (0) 2022.03.09

댓글