-
javascript this와 bindKnowledge/javascript 2019. 9. 15. 13:46반응형
생성자 패턴을 활용하다 보면 javascript의 this가 내 맘 같지 않은 상황을 자주 마주 한다.
예를 들자면 이런 것이다.
1234567891011121314151617181920212223242526272829303132function promotionObj(id) {this.registerEvents(id);}promotionObj.prototype = {// 등록 이벤트registerEvents : function(id){// 뒤로 가기 버튼var backBtn = document.querySelector(".btn_back");backBtn.addEventListener("click",function(){this.backToDetail(id);});},// 상세보기로 이동backToDetail : function(id){location.href = "/reservation/detail?id="+id;}}document.addEventListener('DOMContentLoaded', function() {// promotion 객체 생성});'promotion 객체를 생성할 때 객체내의 registerEvents 함수를 실행하여
backBtn에 backToDetail을 실행하는 클릭 이벤트 리스너를 달아라' 라는 내용의 코드인데
실행해보면 의도대로 작동되지 않는다.
원인을 찾아보면 this.backToDetail(id); 부분이 문제다.
분명 같은 객체 안에 있으니 this.bakcToDetail()이라고 하면 같은 객체안에 있는 backToDetail 함수를 가르킬 것 같지만 console.log를 활용해 확인하면 this가 undefinded라고 출력되기 떄문이다. 왜일까?
이는 javascript에서 this의 특성때문이다.
javascript의 this는 현재 실행 문맥에 따라 결정된다. 즉 해당 메소드의 호출자가 누구인지에 따라 this가 정해진다는 것.
registerEvents() 를 예로 들자면 이 메소드를 호출하는 것은 명백히 promotionObj 객체기 때문에
this를 사용했을 때 이 this가 promotionObj를 가르키고 있음을 알고 의도대로 잘 작동한다.
그런데 자세히 보면 backBtn.addEventListener("click",function(){ this.backToDetail(id); }); 는 registerEvents() 메소드 내부에 있다. 즉 registerEvents() 내부에서 실행될 뿐 이 메소드 자체에 대한 호출자가 명확하지 않고 그게 이 함수에서 this가 undefinded로 확인되는 이유다. 그럼 어떻게 해야할까?
복잡한 원인에 비해 해결책은 간단하다. this는 실행 문맥에 따라 결정되니 상위 메소드(?) registerEvents()의 실행 문맥을 backBtn.addEventListener("click",function(){ this.backToDetail(id); }); 에 bind해주면된다. 설명은 되려 복잡하니 아래 코드를 보자.
123456789101112131415promotionObj.prototype = {// 등록 이벤트registerEvents : function(id){// 뒤로 가기 버튼var backBtn = document.querySelector(".btn_back");backBtn.addEventListener("click",function(){this.backToDetail(id);}.bind(this));}}불필요한 부분을 지운 것을 제외하고 위 코드와 달라진 건 .bind(this)가 추가된 것 밖에 없다.
이것만 추가하면 this가 promotionObj 객체를 가르켜 코드가 의도대로 잘 작동한다.
사실 이게 유일한 해결책은 아니다. ES6의 arrow 함수를 사용하면 bind(this)를 사용하지 않고도 this를 잘 활용할 수 있다고 한다. 근데 이 부분은 잘 모르니 추후 다시 공부해서 포스팅 하는 걸로 하고 this와 bind를 이해하는데 큰 도움을 준 블로그와 edwith 강좌 해당편의 링크를 남기며 포스팅을 마친다
참고
반응형'Knowledge > javascript' 카테고리의 다른 글
Javascript ES6 에 추가된 기능 간단 정리 (0) 2019.11.15 자바스크립트에서 이미지 파일( form data ) 을 ajax로 넘기는 방법! (0) 2019.09.18 javascript 객체 리터럴 패턴과 생성자 패턴, prototype (0) 2019.09.09 데이터 바인딩을 도와주는 handlebars.js 사용법 (0) 2019.08.26 setTimeout에서 this사용하는 방법! (0) 2019.08.26