안녕하세요 이녀석입니다.😎
자바스크립트의 공부방법으로 공식문서인 MDN이나 W3Schools, 도서, 강의가 있을 겁니다.
저도 마찬가지였고 지금도 현재 진행형이죠.
공부하면서 느낀건데 MDN을 보면 번역본이다 보니 이해하기 조금 난해한 부분이 분명 있었고,
저뿐만 아닌 다른 분들도 그런 부분이 있으셨을 거예요.
그래서 제가 이해한 것들을 쉽게 기록을 해보려 합니다.
쉽게 하려다 보니 공식 문서나 여러 강의와 다른 부분이 있을 테지만 제 글을 읽고
분명 도움이 되리라 하는 마음에 포스팅을 작성해 나가도록 하겠습니다.
혹여 부족한 부분과 다른 좋은 내용을 언제든 알려주시면 감사히 배울 테니 언제든 알려주세요.
감사합니다.😎
오늘의 주제는 this입니다😁
자바스크립트에서 빠질 수 없는 주제 중에 하나가 this죠??
결론부터 말씀 드리자면,
[ this, 그것은 재산(함수)을 소유하고 있는 주인(객체)이다. ] 라고 할 수 있겠네요.
객체는 프로퍼티, 메서드를 정의할 수 있습니다.
그리고 이 프로퍼티와 메서드를 재산이라고 할 수 있습니다.
재산에는 돈, 주식, 땅, 운동하는 능력, 코딩하는 능력 등 모든 것이 될 수 있겠죠.
그렇다면 재산(프로퍼티, 메서드)을 소유하고 있는 것은 누구(어떤 객체)일까요?
즉, this는 재산(프로퍼티, 메서드)을 소유하고 있는 소유주(객체)를 가리킵니다.
예시를 통해 누가 재산을 소유하고 있는지 알아볼게요.
// 그냥 평범하게 정의한 함수에서의 this
function art() {
console.log('(1) - 이 예술품의 소유주는 누구일까요? => ', this);
}
// 객체에서 정의한 함수에서의 this
var alex = {
money: 1000,
buildings: 6,
art() {
console.log('(2) - 이 예술품의 소유주는 누구일까요? => ', this);
}
}
재산(함수)을 소유하고 있는 소유주를 알기 위해서는 어떤 객체가 함수를 정의했는지가 가장 중요합니다.
현재 art()는 그냥 평범하게 정의한 함수입니다. 어떤 특정한 객체 내부에서 정의한 함수가 아니라는 말이죠.
어떤 객체의 내부에서 정의를 하고 싶다면 var alex 처럼 정의를 해야 합니다.
art()처럼 평범하게 정의한 함수는(어떤 객체의 내부에서 정의한게 아닌 함수) 소유주가 없는 재산입니다.
소유주가 없는 재산은 어떻게 될까요?
나라(country)에 귀속됩니다. 그리고 소유주는 나라(country)가 되는 것이죠.
그래서 art()에서의 this는 window라는 객체를 가리킵니다.
window객체는 최상위 객체입니다.
즉, 최상위에 있으므로 제일 권력이 쎄다는 뜻이죠.
권력이 제일 쎄므로 window객체를 '나라(country)' 라고 할 수 있으며,
소유주가 없는 재산인 art()는 window객체에 귀속되기 때문에 this가 window객체가 되는 것입니다.
art()처럼 평범하게 정의한 함수는 전역공간에서 정의했다고 할 수 있습니다.
그래서 전역공간에서 정의한 모든 재산(모든 변수, 모든 함수)은 주인이 없으므로 나라(window객체)에 귀속됩니다.
window객체를 살펴보면 art함수와 alex객체가 있는 것을 볼 수 있습니다.
alex객체도 전역공간에서 정의했기 때문에 window객체에 귀속된 것입니다.
즉,
window객체는 전역공간에서 정의한 모든 변수를 프로퍼티로써,
모든 함수를 메서드로써 소유하고 있는 소유주가 됩니다.
그래서
alex는 window객체의 프로퍼티로써 window.alex 로도 동작할 수 있고,
art()는 window객체의 메서드로써 window.art() 로도 실행할 수 있습니다.
그렇지만 ES6에 새롭게 나온 키워드인 let, const로 변수나 함수를 정의하면 조금 다릅니다.
let abel = function() {
console.log('abel 입니다. 소유주는 누구일까요? => ', this);
};
abel()의 this도 역시 window객체를 가리킵니다.
당연합니다. 전역공간에서 정의한 재산(함수)이기 때문에 나라(country)에 귀속됐기 때문이죠.
근데,
window객체를 보면 alex객체, art함수는 있지만 abel함수는 없습니다.
없는 이유는 자바스크립트 자제적인 이슈입니다.
다만,
전역공간에서 let, const 키워드로 변수나 함수를 정의하는 것들은 나라(country)도 모르는 비밀요원이라고 생각하시면 될 것 같습니다.(스파이첩보물의 주인공 같은....ㅎㅎ)
나라(country)도 모르기 때문에 window객체에서도 보이지 않는거죠.
보이지 않기 때문에 window.abel() 은 동작하지 않습니다.
alex.art()는 전역공간이 아닌 alex라는 특정한 객체에서 art()를 정의했습니다.
그래서 alex.art()의 소유주는 alex객체가 되므로 this가 alex객체를 가리키는 것입니다.
다음은 조금 헷갈리거나 특수한 경우의 this를 알아보겠습니다.
1. 중첩된 객체에서의 this
var parent = {
name: '부모님',
hello() {
console.log('안녕하세요 저의 this는 누구일까요?', this);
},
child: {
name: '자식',
hello() {
console.log('안녕하세요 저의 this는 누구일까요?', this);
}
}
}
앞서 말씀 드렸다시피,
함수를 소유하고 있는 소유주를 알기 위해서는 어떤 객체가 함수를 정의했는지가 가장 중요합니다.
parent.hello()의 this는 당연히 parent객체가 됩니다. 위에서 설명한 alex.art()와 같은 맥락이니까요.
그런데 parent.child.hello()의 this는 parent객체가 아닌 parent객체의 프로퍼티인 child객체를 가리킵니다.
parent.child.hello()는 child객체 내부에서 정의했기 때문입니다.
어? 뭔가 법칙아닌 법칙 같은 것을 유추할 수 있지 않나요???
메서드를 사용할때 .(점) 바로 앞에 있는 객체가 this라는 것을 말이죠.
근데 .(점) 바로 앞에 객체가 없는 경우가 있죠?
위에서 설명한 art()같은 경우!!!
이럴 때의 this는 window객체가 됩니다.
함수의 소유주가 누구인지 파악하는 가장 쉬운 방법입니다😎
2. 메서드 내부에서 정의 된 함수에서의 this
var obj = {
parent() {
function child() {
console.log('child함수입니다 저의 this는 누구일까요?', this);
}
console.log('parent함수입니다 저의 this는 누구일까요?', this);
child();
}
}
obj.parent()의 this는 obj객체입니다.
왜인지는 이젠 무조건 아시겠죠?
반면에,
child()의 this는 window객체입니다.
child()는 객체에서 정의한 함수가 아닌 평범하게 정의한 함수이기 때문입니다.
평범하게 정의했으므로 소유주가 없겠죠?
그래서 나라(country)에 귀속되기 때문에 this는 window객체가 된 것입니다.
근데 잠깐! 기억나시는게 없나요?😮😮😮
프로토타입(prototype)의 모든 것 - 2/3편 : 은행의 서비스 저장소
안녕하세요 이녀석입니다.😎 자바스크립트의 공부방법으로 공식문서인 MDN이나 W3Schools, 도서, 강의가 있을 겁니다. 저도 마찬가지였고 지금도 현재 진행형이죠. 공부하면서 느낀건데 MDN을 보면
skyhyunjinlee.tistory.com
지난 포스팅인 '프로토타입(prototype)의 모든 것'에서 함수도 객체라고 했습니다!
그렇다면 child()도 객체에서 정의한 함수가 되는 것이 맞는게 아닐까요?
객체인 obj.parent()내부에서 정의한 child()의 this가 obj.parent()여야 하는 것이 옳은게 아닐까요?
정답은 X 입니다.
child()의 this는 window객체가 맞습니다.
child()를 실행할 때 obj.parent.child()처럼 실행하지 않았죠?
child()앞에 .(점)이 없으므로 this는 window객체가 되는 것이 맞습니다.
child()의 소유주가 window객체이지만,
전역공간에서 let, const로 정의한 변수나 함수처럼 child()는 window객체에서 찾아볼 수 없습니다.
child()도 비밀요원이기 때문이죠.(지금의 경우는 스코프라는 개념 때문에 비밀요원이 된 것입니다 나중에 설명드릴게요)
만약에 this가 obj.parent()가 되려면 아래처럼 코드를 작성해야합니다.
var obj = {
parent() {
console.log('parent함수입니다 저의 this는 누구일까요?', this);
}
}
obj.parent.child = function() {
console.log('child함수입니다 저의 this는 누구일까요?', this);
};
3. 콜백함수에서의 this
콜백함수는 A함수의 인자로 B함수가 사용될 때, 인자로 사용되는 B함수를 콜백함수라고 부릅니다.
(지금은 콜백함수를 자세히 모르셔도 됩니다.)
var firstNames = ['김', '이', '박', '최', '정'];
forEach()의 인자로 function(){ console.log(this) } 라는 익명함수를 할당했습니다.
이때, 이 익명함수가 콜백함수가 되는 것이죠.
위 이미지처럼 콜백함수에서의 this는 window객체가 됩니다.
이 콜백함수가 객체 내부에서 정의된 함수가 아니기 때문에 나라(country)에 귀속된 것이죠.
그렇지만 지금의 경우도 window객체에서 이 익명함수를 찾아 볼 수 없습니다.
귀속되었을지라도,
이름이 없는 재산이므로 나라(country)에서 찾아 볼 수 없다고 생각하시면 됩니다.
예외도 있습니다.
이벤트를 사용할때의 콜백함수의 this입니다.
// HTML
<div>HELLO</div>
var div = document.querySelector('div');
이벤트를 사용하기 위한 함수인 addEventListener()의 두 번째 인자로 function(){ console.log(this) } 라는 익명함수를 할당했습니다.
클릭을 하면, 이번에는 window객체가 아닌 이벤트를 사용한 div요소가 this가 됩니다.
제가 여자친구에게(...현실은 없지만) 프로포즈를 위한 이벤트를 준비한다고 생각해볼게요.
프로포즈를 하는 주체가 나라(country)가 되면 안되겠죠?
여자친구가 나라(contry)랑 결혼할 수는 없잖아요...?ㅎㅎ
그래서
addEventListener()의 콜백함수의 this는 이벤트를 사용하는 대상이 무엇인지 알려주기 위한 this라고 보시면 됩니다.
4. new 키워드를 사용할 때의 함수
function Person() {
if(new.target) {
console.log('new 키워드를 사용한 this는 무엇일까요? => ', this);
} else {
console.log('그냥 this는 무엇일까요? => ', this);
}
}
Person()은 객체 내부에서 정의한게 아니기 때문에 new키워드 없이 실행한다면
this는 window객체가 됩니다.
`
그렇지만 new키워드를 사용하여 실행한다면 { }(빈 객체 )가 됩니다.
function Person() {
// 자바스크립트가 자체적으로 할당함
// this = {};
this.sayHello = function(){
console.log(this);
}
// 자바스크립트가 자제척으로 return this를 생략함
// return this;
}
var p = new Person();
new키워드를 사용하면 위 코드처럼
자바스크립트가 자체적으로 함수 내부에서 { }(빈 객체)를 만들어 this에 할당하기 때문입니다.
this가 { }(빈 객체)를 참조하므로,
즉 this가 객체이므로 프로퍼티와 메서드를 추가할 수 있겠죠?
그래서 생성자 함수로 객체를 만들 때 this.name, this.age 등등 처럼 사용했던 것입니다.
그리고 return이 없더라도 this를 return하기 때문에 변수 p에 객체가 할당되는 것입니다.
그래서 sayHello함수는 객체 내부에서 정의한 함수가 되므로 sayHello함수의 this는 p변수가 참조하는 객체가 됩니다.
'JAVASCRIPT' 카테고리의 다른 글
모듈(export & import) 한 번에 끝내기!! (0) | 2023.06.21 |
---|---|
스코프(Scope)는 어망(그물)이다. (0) | 2023.02.01 |
객체 참조, 그것은 '공동명의'이다. (0) | 2023.01.17 |
프로토타입(prototype)의 모든 것 - 번외편 : MDN도 다 이유가 있었구나! (0) | 2023.01.12 |
프로토타입(prototype)의 모든 것 - 3/3편 : 앱(App)으로 가능해진 은행 업무 (0) | 2022.09.07 |