this는 자신이 속한 객체나 자신이 생성할 인스턴스를 가리키는 참조 변수this에 바인딩할 객체가 동적으로 결정된다this는 Global Object를 가리킨다Global Object는 window 객체, 서버 상에서 Global Object는 global 객체function func() {
  console.log(this); 
}
func(); // window
func() 방식으로 함수 호출하는 방식이 일반적인 함수 호출 방식const name = "jhj";
function func() {
  console.log(this.name); 
}
func(); // jhj
name은 Global Object인 window의 속성으로 추가된다 → window.name 생성console.log(this.name) == console.log(window.name)'use strict';
const name = "jhj";
function func() {
  console.log(this.name); 
}
func(); // error
strict mode에서 this는 window를 가리키지 않는다const obj1 = {
  name: "jhj",
  getName: function() {
    console.log(this.name);
  }
}
const obj2 = {
  name: "krkorklo"
}
obj2.getName = obj1.getName;
obj1.getName(); // jhj
obj2.getName(); // krkorklo
new 연산자를 붙여 호출하면 생성자 함수로 동작this 바인딩this를 사용해 property 생성function Person(name) {
  this.name = name;
}
const person = new Person("jhj");
console.log(person); // jhj
Person.prototype을 프로토타입 객체로 가지는 객체가 생성new 연산자를 붙이지 않는 경우
function Person(name) {
  this.name = name;
}
const person = Person("jhj");
console.log(person); // undefined
console.log(window.name); // jhj
new 없이 생성자 함수를 호출하면 this를 암묵적으로 반환하지 않아 undefined가 반환new 없이 생성자 함수를 호출한 경우 Persom 내부의 this는 전역 객체를 가리키게 되어 전역 변수에 바인딩this에 바인딩될 객체는 함수 호출 패턴에 따라 JavaScript 엔진이 동적으로 바인딩apply, call, bind 사용this를 특정 객체에 바인딩const Person = function (name) {
  this.name = name;
}
const per = {};
Person.apply(per, ['jhj']);
console.log(per); // { name : 'jhj' }
Person 함수의 this가 per 객체가 된다this(per)에 name property가 없으므로 name이 동적으로 추가되고 값이 할당apply와 기능은 같지만 배열 형태로 arguments를 넘기는 것이 아니라 하나씩 인자로 전달Person.call(per, 'jhj');
call, apply와 달리 함수를 실행하는 것이 아니라 연결만 하는 것const Person = function (name) {
  this.name = name;
  console.log(this);
};
const per = { age: 23 };
const newPer = Person.bind(per, "jhj");
newPer();
function 키워드 없이 => 화살표 표시로 함수를 선언const func = () => console.log("function");
this가 존재하지 않기 때문에 상위 환경의 this를 참조한다this가 동적으로 바인딩되지만 화살표 함수에서는 선언될 시점의 상위 스코프가 this로 정적 바인딩function Person(name) {
  this.name = name;
}
Person.prototype.console = function (arr) {
  // this는 상위 스코프인 Person 메소드 내의 this를 가리킨다
  return arr.map(x => `${this.name}  ${x}`);
};
const person = new Person('krkorklo');
console.log(person.console(['hi', 'hello']));
apply, call, bind를 사용해 this를 변경할 수 없다const person = {
  name: "jhj",
  console: () => console.log(`hi ${this.name}`)
}
person.console(); // hi undefined
this가 상위 컨텍스트의 전역 객체(window)를 가리키게 된다const person = {
  name: "jhj"
}
Object.prototype.getName = () => console.log(`hi ${this.name}`);
person.getName(); // hi undefined
this가 상위 컨텍스트의 전역 객체를 가리키게 되므로 일반 함수를 사용해야한다prototype property를 가져 prototype property가 가리키는 프로토타입 객체의 constructor를 사용해서 객체 생성prototype property를 가지지 않으므로 화살표함수를 사용하면 안된다const Person = () => {};
const person = new Person(); // Person is not a constructor
window)를 가리킨다let button = document.getElementById('button');
button.addEventListener('click', () => {
  console.log(this === window); // true
});
button.addEventListener('click', function() {
  console.log(this === button); // true
});
참고자료
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this
https://poiemaweb.com/js-this
https://poiemaweb.com/es6-arrow-function