이번 시간에는 면접 단골 질문 중에 하나인 this
에 대해서 알아보자!!
console.log(this); // window
function 함수() {
console.log(this); // window
}
"use strict";
console.log(this); // window
function 함수() {
console.log(this); // undefined
}
=> 크게 중요하지는 않지만, 그냥 알아만 두자!
window는 JS의 기본 함수들이다.
좀 더 정확하게 말하자면,
window는 모든 전역변수, 함수, DOM을 보관하고 관리하는 전역객체이다.
let kim = {
name: "kim",
first: 10,
second: 20,
sum: function () {
// kim.first로 해도 돌아가지만, 객체 이름은 k로 바꾸면 코드는 동작하지 않는다.
// return kim.first + kim.second;
// 그리고 논리적으로 생각해봐도
// 상위 함수가 어떤 이름을 갖고 있을지 알아내는 것은 모든 상황에서 가능한 일은 아니다.
return this.first + this.second;
// this는 자신이 속해있는 객체를 가리킨다.
},
};
console.log(kim.sum()); // 30
kim
이라는 객체에서 first와 second 값을 더해주는 sum
메소드를 만들어준다면, 어떤 식으로 반환 값을 작성해야 할까??
가장 직관적인 방법은 위의 코드처럼 하는 방법이다.
그러나, kim
이라는 객체 이름이 cho
로 바뀐다면, 해당 return 값은 작동하지 않는다.
또한, 논리적으로 생각해봐도 상위 함수가 어떤 이름을 갖고 있을지 알아내는 것은 모든 상황에서 가능한 일은 아니다.
sum()
의return
코드의 문제점
- 객체의 이름이 바뀔 때마다, 코드를 변경해줘야 한다.
- 상위 함수가 어떤 이름을 갖고 있을지 알아내는 것은 모든 상황에서 가능한 일은 아니다.
이러한, 번거로움을 해결하기 위해서 나온 문법이 this
이다.
let kim = {
name: "kim",
first: 10,
second: 20,
sum: function () {
return this.first + this.second;
// this는 자신이 속해있는 객체를 가리킨다.
},
};
console.log(kim.sum()); // 30
this
는 자신이 속해있는 객체를 가리킨다. 이렇게 바꿔주면, kim
의 이름이 어떻게 바뀌어도 sum()
은 코드 변경 없이 잘 작동한다.
this
덕분에 그 객체가 내부적으로 가지고 있는 상태를 함수에서 참조할 수있게 됐다.
- 지금부터 특정 상황에서
this
는 어떤 어떤 의미를 가리키는지 세분화해서 알아보자!!
this
는 함수 내에서 함수 호출 맥락(context)를 의미한다. 맥락이라는 것은 상황에 따라서 달라진다는 의미인데 즉 함수를 어떻게 호출하느냐에 따라서 this
가 가리키는 대상이 달라진다는 뜻이다. 함수와 객체의 관계가 느슨한 자바스크립트에서 this
는 이 둘을 연결시켜주는 실질적인 연결점의 역할을 한다.
function func() {
if (globalThis === this) {
// console.log(this);
return globalThis === this;
}
}
console.log(func()); // true
여기서 func
라는 함수는 globalThis
라는 전역 객체의 메소드라고 볼 수있다.
그래서, 우리는 이런 결론을 내릴 수있다.
객체의 소속인 메소드의 this
는 그 객체를 가르킨다.
이번에는 메소드를 호출했을 때, This
값을 살펴보자.
메소드 : 객체의 속성 값으로 담긴 함수를 특별하게 부르는 말
이 객체를 담고 있는 변수 test
와 이 메소드 안에 담겨 있는 this
의 값이 같은지 확인해보자.
let test = {
func: function () {
if (test === this) {
// return console.log(this);
return test === this;
}
},
};
console.log(test.func()); // true
객체의 소속인 메소드의 this
는 그 객체를 가르킨다.
아직 JS 생성자에 대해서 익숙하지 않다면, JS 생성자와 new 키워드편을 먼저 보고 오시길 바랍니다.
// ex 1 => Func()를 함수로 활용할 때,
function Func() {
// let이나 var로 할당 되지 않았기 때문에
// funcThis는 전역변수이다.
funcThis = this;
}
let o1 = Func();
if (funcThis === globalThis) {
console.log("funcThis는 전역변수이다."); // 콘솔 값이 출력 됨!!
}
// 현재까지 funcThis는 전역 변수이다.
// ex 2 => Func()를 생성자로 활용할 때,
let o2 = new Func();
if (funcThis === o2) {
console.log("o2 와 funcThis는 같다"); // 콘솔 값이 출력 됨!!
}
위의 예제 코드를 통해, 우리가 알 수 있는 사실은
Func()
가 생성자로써 사용되면,// function Func() { // funcThis = this; // return funcThis; // }
Func()
내부의this
값은 생성될 객체를 가리킨다.
하지만,Func()
를 함수로 호출하면, 이 함수 안에서this
의 값은 window를 가리킨다.
즉, 생성자 안의this
는 그 생성자가 만든 객체를 가리킨다.
전통적으로 메소드는 해당 객체에 종속되있다.
그러나, 함수의 메소드인 apply, call을 이용하면 this의 값을 제어할 수 있다.
다시 말해, 메소드가 아닌 외부함수를 메소드처럼 사용할 수있게 된다. 즉, 함수의 재사용성이 높아진다.
let o = {}
let p = {}
function func(){
switch(this){
case o:
console.log('o');
break;
case p:
console.log('p');
break;
case globalThis:
console.log('window');
break;
}
}
func(); // window
func.apply(o); // o
func.apply(p); // p
객체 안에 있는 함수를 "메소드"라고 한다.
그리고 신문법이 등장하면서 이 메소드를 넣을 수 있는 방법이 좀 더 간단해졌는데, 이 부분에 대해서 알아보자!
// 전통적인 방법
let obj = {
함수 : function(){
console.log("it works");
}
}
obj.함수(); // 'it works'
// 신문법
// 중간에 function 생략 가능
let newObj = {
함수(){
console.log("it works");
}
}
newObj.함수(); // 'it works'
새로운 방법은 이렇게 중간에 function
을 생략할 수있다.
var 오브젝트2 = {
data : {
간지함수 : function(){ console.log(this) }
}
}
오브젝트2.data.간지함수();
간지함수()를 담고있는 주인님인 오브젝트2.data
<script>
(1)
function 간지나는함수(){
console.log(this)
}
(2)
window.간지나는함수 = function(){ console.log() };
</script>
(2)문법은 window
라는 오브젝트에 함수 자료를 추가하는 문법일 뿐입니다. 어려운거 없습니다.
아무튼 결론은 전역함수 만들거나 전역변수 만드시면 저렇게 window {오브젝트}
안에 담긴다는 소리입니다.
우리가 일부러 하지 않아도 변수나 함수 쌩으로 만들면 자바스크립트가 자동으로 알아서 window
안에 담습니다.
그럼 이제 function 문법의 동작원리 하나를 알았으니 다시 한번 this를 여기서 출력해봅시다.
<script>
function 간지나는함수(){
console.log(this)
}
</script>
여기서 this는 무슨 값이 나올까요?
this는 아까 2번에 의하면 내 메소드를 포함하고 있는 주인님 오브젝트를 출력시켜준댔죠?
간지나는함수()를 포함하고 있는 주인님 오브젝트가 무엇입니까?
=> window
오늘 TIL은 코드스테이츠에서 학습한 내용과 아래의 출처에서 학습한 내용을 바탕으로 작성됐다.