JavaScript

[JS] JavaScript에서 다양한 this

PEAZH 2024. 10. 8. 16:54
반응형

JavaScript에서 this

JavaScript에서 this객체를 가르키는 키워드로, 현재 실행 중인 함수의 문맥(context)을 가르킨다.

this가 가르키는 대상은 함수 호출 방식에 따라 달라진다.


01) 전역 범위

  • 전역 범위에서 this는 기본값으로 전역 객체를 의미
  • 브라우저에서 전역 객체는 window 객체로, 브라우저 환경에서 제공되는 다양한 API를 제어할 수 있음
console.log(this); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}

 

02) 함수 호출

  • 일반 함수에서 this는 기본적으로 전역 객체를 가리킴
  • 호출한 객체가 없으므로 window 객체가 출력됨
function printThis() {
  console.log(this);
}
printThis(); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}

 

03) 메서드 호출

  • 객체 안에서 메서드를 호출할 때, this는 해당 객체(=person)를 가리킴
let person = {
  name: "peazh",
  age: 20,
  printThis: function () {
    console.log(this);
  },
};
person.printThis(); // { name: "peazh", age: 20, hello: f }
function printThis() {
  console.log(this);
}

let person1 = {
  name: "여름1",
  printThis: printThis,
};
person1.printThis(); // {name: '여름1', printThis: ƒ}

let person2 = {
  name: "여름2",
  printThis: printThis,
};
person2.printThis(); // {name: '여름2', printThis: ƒ}

let person3 = {
  name: "여름3",
  printThis: printThis,
};
person3.printThis(); // {name: '여름3', printThis: ƒ}

 

🔻예외 경우

let person = {
  name: "peazh",
  age: 20,
  printThis: function () {
    console.log(this);
  },
};

let printThis = person.printThis;
printThis(); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
  • 객체의 메서드를 변수에 할당한 후 호출하면, 메서드와 객쳉의 연결이 끊어져 this는 전역 객체를 가리키게 됨
  • 그래서 메서드 호출이 아닌 일반 함수 호출처럼 동작함

 

04) 화살표 함수

  • 자신이 선언된 외부 스코프에서 this를 그대로 상속받음
  • 정적으로 바인딩(선언된 시점의 스코프에 따라 결정)되며, 화살표 함수의 내부 this는 변하지 않음

 

🔻일반 함수를 사용

let person = {
  name: "peazh",
  age: 20,
  hello: function () {
    setTimeout(function () {
      console.log(this)
    }, 1000);
  },
};
person.hello(); //Window {window: Window, self: Window, document: document, name: '', location: Location, …}
  • setTimeout 같은 비동기 함수의 콜백으로 전달된 함수는 특별히 다른 바인딩이 없는 한 전역 스코프에서 실행
  • 콜백 함수는 객체의 메서드로 호출된 것이 아니라 단독으로 호출된 것으로, this가 전역 객체를 참조함

 

🔻일반 함수를 화살표 함수로 변경

let person = {
  name: "peazh",
  age: 20,
  hello: function () {
    setTimeout(() => {
      console.log(this);
    }, 1000);
  },
};
person.hello(); // {name: 'peazh', age: 20, hello: ƒ}
  • this는 화살표 함수를 포함하고 있는 외부 스코프 person 객체를 가리킴

 

🔻화살표 함수를 사용하면 안되는 경우

let person = {
  name: "peazh",
  age: 20,
  hello: () => {
    console.log(this);
  },
};
person.hello(); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
  • hello의 외부 스코프는 전역 스코프이기 때문에, 전역 스코프의 this인 window 객체를 반환
  • 이와 같은 경우에는 화살표 함수보다는 일반 함수를 사용해야 함

 

05) 이벤트 핸들러

 

🔻일반 함수

let btn = document.querySelector("button");
btn.addEventListener("click", function () {
  console.log(this); // <button id="btn">버튼</button>
  console.log(this === btn); // true
});
  • 일반 함수에서 this는 호출되는 DOM 요소(이벤트가 발생한 대상)를 가리킴

 

🔻화살표 함수

let btn = document.querySelector("button");
btn.addEventListener("click", () => {
  console.log(this); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
});
  • 이벤트 핸들러로 전달될 함수의 this는 호출 시점에 결정되는데, 화살표 함수는 그 자체로는 this를 바인딩하지 않기 때문에 전역 객체를 참조함

 

06) 엄격 모드

  • 엄격 모드(Strict Mode)에서는 기본값이 전역 객체가 아닌 undefined로 설정되어, 더욱 엄격하게 검사함

 

🔻non strict mode

function printThis() {
  console.log(this);
}
printThis(); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}

 

🔻strict mode

'use strict'
function printThis() {
  console.log(this);
}
printThis(); // undefined

 

07) bind 메서드 사용

  • bind를 사용하여 this의 값을 명시적으로 설정할 수 있음
  • 원하는 함수에 바인드 메서드를 호출한 뒤 객체를 파라미터로 전달해주면 됨
function printThis() {
  console.log(this);
}
// this를 마음대로 변경하기
let person = {
  name: "한여름",
};

let printThis1 = printThis.bind(person);
printThis1(); // {name: '한여름'}

 

🔻주의사항

let person1 = {
  name: "한여름",
};
let person2 = {
  name: "최여름",
};

let printThis1 = printThis.bind(person1);
let printThis2 = printThis1.bind(person2);
printThis2(); // {name: '한여름'}
  • bind는 한 번 바인딩된 함수의 this 값을 다시 바인딩할 수 없음
  • 그래서 printThis1을 person1에 바인딩한 후 다시 바인딩을 시도해도, '최여름'이 아닌 '한여름'이 출력됨

 

🔻bind 메서드 사용 전

let person = {
  name: "peazh",
  age: 20,
  hello: function () {
    setTimeout(function () {
      console.log(this.name);
      console.log(this.age); // undefined
    }, 1000);
  },
};
person.hello();
  • setTimeout에서의 콜백 함수가 일반 함수로 호출되기 때문에 this는 전역 객체를 가리킴
  • 그래서 this.name, age는 undefined가 출력됨

 

🔻bind 메서드 사용 후

let person = {
  name: "peazh",
  age: 20,
  hello: function () {
    setTimeout((function () {
      console.log(this.name); // peazh
      console.log(this.age); // 20
    }).bind(this), 1000);
  },
};
person.hello();
  • bind를 사용하여 this를 명시적으로 person 객체로 고정

 

반응형