어떤 객체를 가리키는 키워드이다.
무슨 객체를 가리키는지 정확하게 알 수 없다.
this가 가리키는 객체는 상황에 따라서 달라지기 때문.
"this는 함수를 호출한 객체이다."
[1. 전역 문맥]
전역 문맥에서 this는 어떤 값을 가질까?


전역적인 실행 맥락(함수 외부)에서 this를 출력하면,
window가 나온다. 이것은 'window 객체'이며 브라우저에 대한 정보를 갖고 있는 전역 객체임.
if문을 통해 this를 출력하더라도 전역적인 문맥이기 때문에 window 객체가 출력된다.


지금까지의 결론 : 전역적인 문맥에서 this에 접근하면 this는 window 객체가 된다.

파일 상단에 'use strict'라고 작성하면 엄격 모드가 활성화된다.


↑ 이후 this를 전역적인 문맥에서 접근해보면 위와 동일하게 window 객체가 출력된다.
: 'use strict'를 사용해서 엄격 모드를 활성화시킨다는 것은 자바스크립트한테 내가 쓰는 js 문법을 좀 더 엄격하게 검사해 달라는 것.



전역적인 맥락에서의 this는 엄격 모드와는 관계 없이 항상 window 객체를 가리킨다.
[3. 함수 문맥]

함수 내부에 있는 this는 함수 호출 방법에 따라 값이 달라진다.
this는 this를 포함하고 있는 함수를 호출한 객체가 된다.
function이라는 키워드를 사용해서 함수를 정의하게 되면, 함수는 window 객체에 등록이 된다.

콘솔에 window를 찍어서 확인해보면,

일단 window 객체가 출력.

쭉 내려보면 내가 정의한 main이라는 함수가 window 객체 내부에 들어있다는 것을 확인할 수 있다.

main 함수를 호출.

this는 window 객체가 된다.
전역적으로 함수를 호출하는 것은, window.main(); 이렇게 호출하는 것과 같다. 
main이라는 함수는 window 객체에 등록된 함수이기 때문.
this는 함수를 호출한 객체라고 했는데, main 함수를 직접적으로 호출한 객체는 window임. window.main();으로 함수를 호출했기 때문. 그렇기에 함수 안에 있는 this 값은 window 객체가 되는 것임.
여기서 한 가지 예외가 존재.
만약 엄격 모드를 활성화시킨다면?


엄격 모드를 활성화시킨 뒤, 그냥 main으로 함수를 호출하게 되면 this의 값이 undefined가 된다. this 값을 window로 만들어 주고 싶다면,

이렇게 직접적으로 window.을 붙여 호출해야 함.

만약, 함수 내부에서 엄격 모드를 활성화한다면?

위와 마찬가지로, main으로만 함수를 호출한 경우에 undefined 출력.
window.을 붙여 함수를 호출하면 this의 값은 window가 된다.
[4. 객체의 메서드]
object라는 객체를 하나 만들어줌.
메서드를 하나 만듦.
soccer이라는 함수를 object 객체의 메서드로 넣어본다면,

메서드라는 것은 객체의 속성으로 쏙 넣어진 함수를 의미한다.

그럼, object 객체의 메서드로 soccer 함수를 호출한다면?

soccer 함수 안에 있는 this는 내가 만든 object가 된다.
함수 내부에 있는 this는 함수를 호출한 객체가 된다.
soccer이라는 함수는 object 객체가 호출시킨 것이므로.
객체의 다른 속성에 접근할 때 유용.
this는 object를 가리키고 있으므로, 
this.name으로 '손흥민'에 접근할 수 있다. 
결론 : this는 함수를 호출한 객체이다. 오직 함수를 호출한 객체가 누구인지만 중요한 것.

만약 코드 아래에 'soccer2'라는 변수를 만들고, 그 안에 object.soccer이라고 해서 soccer 함수를 할당한 다음, soccer2라는 변수에 담겨 있는 함수를 호출하면, window 객체가 출력된다.

왜냐하면 더이상 soccer2 함수를 호출한 객체는 object 객체가 아니기 때문. soccer2 함수는 전역적으로 호출된 것이므로.
여기서 한 가지 꼭 짚고 넘어가야 할 점.
this는 함수가 정의된 위치나 방법에 영향을 받지 않는다는 것.
일단 soccer 함수를 지워주고, object 객체 외부에 soccer 함수를 만들어줌. 
soccer 함수를 object 객체의 외부에 만들어준 것임.
바깥에 있는 soccer 함수를 object 객체의 메서드로 넣어주겠음.
키와 값이 같은 이름이기 때문에 생략해도 됨. (soccer : soccer 하지 않아도 된다는 말). 이런 식으로 soccer 함수를 먼저 정의한 후, 객체를 만들어서 객체의 구성원으로 soccer 함수를 포함을 시켜주더라도, this는 object 객체가 된다. 함수가 object 객체 밖에서 정의되었든, object 객체의 내부에 포함되었든 상관 없이 soccer 함수를 호출한 객체가 this의 값이 된다. 
object 객체가 만들어진 다음에 object에다가 soccer 함수를 추가해줘도 this 값은 object가 됨.
그럼 이번엔, object 내부에 다른 객체를 만들어 준 후, soccer 함수를 집어 넣는다면?

함수를 호출, 이번엔

이렇게 호출해 보겠음. this의 값은 무엇이 될까?

smallObject가 출력됨.
이것도 마찬가지로 soccer 함수를 직접적으로 호출한 객체는 smallObject이기 때문에 this 값은 smallObject가 된다.
어떤 함수의 this 값이 궁금하다면, .바로 왼쪽에 있는 객체를 보면 된다.
동적으로 바뀌는 this 값을 하나하나 추적하기 귀찮음.
만약 this 값이 바뀌지 않도록, 내가 원하는 객체로 고정하고 싶다면?
함수를 누가 어떻게 호출하든 상관 없이...
그럴 때는 Bind를 이용하면 된다.
함수에다 내가 원하는 객체를 바인딩(묶어주는 것).
맨처음 했던 것처럼 soccer 함수를 만들어주기.


window 객체 출력.
근데 나는 더이상 this 값이 window가 되는 것을 원치 않음.
내가 원하는 객체를 this 값으로 설정하고 싶어짐.
soccer 함수에 다른 객체를 바인딩시켜주겠음.
soccerBind라는 변수에다가 soccer 함수를 할당하는데, 함수 뒤에 .bind를 붙이기. bind의 인자로 내가 원하는 객체를 넣어주면 됨. soccerBind라는 함수를 호출해 보겠음. 

this 값이 더이상 window 객체가 아니라, 내가 만든 객체로 출력됨.
아무리 새로운 object 객체를 만들고 그 내부에 soccerBind 함수를 넣고 object.soccerBind();라고 호출해줘도 this의 값은 내가 만든 객체로 출력됨. 

soccerBind 함수를 호출한 객체는 object 객체임에도 불구하고, 내가 설정한 객체로 출력됨.
'bind'라는 것은 새로운 함수를 반환해준다. 내가 만든 soccer 함수에다 bind를 붙이면 내가 넣어준 객체가 this 값으로 설정된 새로운 함수를 반환해준다. 그래서 그 새로운 함수가 soccerBind에 들어가서 soccerBind를 호출해준 것.
**Bind 주의할 점


한 번 더 반복해서 바인딩을 해준 빈 객체가 this 값으로 출력되지 않음. 무시해버림. (반복 바인딩을 하면 무시함)

다시 돌아와 이 코드에서의 this 값을 내가 원하는 걸로 바꿔주고 싶다면? 함수에다 바인딩을 해주면 됨. 

this 값이 내가 넣어준 객체로 출력되는 것을 알 수 있음.
함수를 DOM 요소의 이벤트 처리기로 사용할 때 this 값은 어떤 식으로 설정되는지 알아보자. 내가 버튼을 클릭하거나 스크롤을 한다든지 그럴 때 발생하는 '이벤트'를 처리할 때 '이벤트 리스너'를 사용한다.



버튼을 클릭할 때마다 함수가 호출될 것임. 그때의 this 값을 콘솔에 출력해 보겠음. 
버튼을 클릭할 때마다 this 값으로 버튼 요소가 출력된다. 함수를 DOM 요소의 이벤트 처리기로 사용한다면, this의 값은 이벤트를 발사한 요소로 설정된다. 

this는 이벤트 타겟인 버튼 요소가 맞다는 뜻.

화살표 함수는 자바스크립트 ES6 버전의 문법임.
함수를 더 간결하게 사용할 수 있다.
전통적인 함수에서의 this는 함수 호출 방법에 따라 동적임.
화살표 함수는 어떤 방법으로 호출하든 this 값이 변하지 않음.
그 함수를 감싸는 스코프의 this를 그대로 가져와서 사용하기 때문.
하지만 화살표 함수가 전통적인 함수를 모두 대체할 수는 없기에 두 방식 다 알고 있어야 함.