다른 언어와 달리 자바스크립트의 독특한 특징 중 하나는 this
의 용법입니다. this
가 상황에 따라 가리키는 것이 다르기 때문에 잘 알아두어야 원하는 대로 this
를 조작할 수 있습니다.
this를 따로 혼자 호출한 경우입니다. 단독으로 this를 호출하면 window를 가리킵니다.
const x = this;
console.log(x); //window
this를 단독으로 사용하면, this는 글로벌 객체
를 가리킵니다. 또한 Strict(엄격) 모드에서 단독으로 사용된 this는 undefined
를 가리킵니다.
함수에서 this를 그냥 호출하게 되면 다음과 같이 window를 가리킵니다.
const func = () => {
return this; //window
};
이번에도 함수 내에서 this를 사용하면 글로벌 객체
를 가리킵니다. 또한 Strict 모드에서도 undefined
를 가리킵니다.
단, 함수 내에서 this가 글로벌 객체를 가리키지 않게 하는 방법이 있는데요. 바로 애로우 함수를 이용하는 방식입니다. 애로우 함수가 전역으로 실행되더라도, 애로우 함수의 this는 바로 바깥의 함수나 클래스의 this를 가리키게 해줍니다.
방금까지 본 두 경우는 this가 모두 글로벌 객체를 가리켰습니다. 그래서 this는 기본적으로 글로벌 객체를 가리킨다고 알아두고 이제부터는 글로벌 객체가 아닌 것을 가리키는 경우를 알아보겠습니다.
객체 메소드 내부에서 this를 사용하는 경우입니다.
const obj = {
x: 100,
printX: function() {
return this.x;
},
};
obj.printX(); //100
객체 메소드 내부의 this는 메소드를 호출한 객체를 가리킨다는 것을 알 수 있습니다.
추가적으로 객체 내부에 동일한 이름의 프로퍼티를 추가하고 동일한 메소드를 넣으면 this는 가장 최근의 객체를 가리키게 됩니다.
const obj = {
x: 100,
printX: function() {
return this.x;
},
};
obj.innerObj = {
x: 404,
printX: function() {
return this.x;
}
};
obj.innerObj.printX();
생성자 내부에서 this를 쓰는 것을 많이봤는데, 이때 this는 무엇을 가리킬까요?
function Student(name, id) {
this.name = name;
this.id = id;
}
let student01 = new Student('무지', 101);
console.log(student01.name); //'무지'
console.log(student01.id); //101
생성자 내의 this는 생성한 인스턴스 객체를 가리킵니다.
하지만 주의할 점이 있는데요. 생성자도 함수의 일종이라는 점 입니다. 그래서 new 연산자를 통해 객체를 인스턴스화 한 것이 아니면 생성자가 아닌 일반 함수로 인식이 되어 글로벌 객체를 가리키게 됩니다.
이러한 문제는 ES6에서 class와 constructor명령이 추가되면서 해결되었습니다. new 연산자를 빼먹지 않게 방지해줍니다. 또한 constructor 생성자 함수 내에서 사용되는 this도 인스턴스 객체를 가리킵니다.
이벤트 리스너
는 웹 페이지에서 이벤트가 발생했을 때 그에 대한 동작을 정의하는 코드들입니다.
document.body.addEventListdocument.body.addEventListener('click', function () {
console.log(this); //<body>
});
이벤트 리스너에서 this를 사용하면, 해당 이벤트의 대상이 되는 DOM 요소를 가리킵니다.
this
를 명시적으로 바인딩 한다는 것은 this가 가리키는 대상을 지정해준다는 의미입니다.
let sayYaho = {z: '야호'};
function whatIsThis() {
console.log(this);
};
whatIsThis(); //window
whatIsThis.bind(sayYaho).call(); //sayYaho 객체
whatIsThis.call(sayYaho); //sayYaho 객체
whatIsThis.apply(sayYaho); //sayYaho 객체
명시적으로 bind(), call(), apply() 메소드를 통해 this를 바인딩하면 this가 인수로 전달된 객체를 가리킨다는 것을 알 수 있습니다.