[자바스크립트] - this란?

1️⃣ this란 무엇일까?

자바스크립트를 사용할 때 this라는 개념이 많이 사용된다. 이 때마다 개념이 헷갈려서 잘 적용이 된다 싶으면 넘어가곤 했다. 그래서 이번엔 개념을 확실히 잡아야 겠다고 생각했다.

MDN에서 보면 대부분의 경우 this의 값은 함수를 호출한 방법에 의해 결정된다고 써져있다. 

만약 호출한 놈이 없을 때는 기본값으로 window 객체가 반환된다.

// 웹 브라우저에서 window 객체가 전역 객체임
console.log(this === window); // true

2️⃣ this는 호출한 놈

대부분의 경우 this의 값은 호출한 방법에 의해 결정된다.

function printThis() {
  console.log(this);
}
printThis(); // window 객체

let person1 = {
  name: '김길동',
  whoIsThis: printThis,
};

let person2 = {
  name: '홍길동',
  whoIsThis: printThis,
};

let person3 = {
  name: '짐길동',
  whoIsThis: printThis,
};

person1.whoIsThis(); // person1 객체	"김길동"
person2.whoIsThis(); // person2 객체	"홍길동"
person3.whoIsThis(); // person3 객체	""짐길동"

이 처럼 호출한 객체가 존재한다면 해당 객체의 값을 반환해주는 역할을 한다.

3️⃣ bind 함수

만약 내가 원하는 객체로 this를 변경하고 싶다면 ES6부터는 bind함수로 바인딩 해줄 수 있다.

function print() {
  console.log('this: ', this);
  console.log('this.fullname: ', this.fullname);
}

let person1 = {
  fullname: '홍길동',
};
let person2 = {
  fullname: '김길동',
};
let bindPrint = print.bind(person1); // person1 객체로 바인딩
bindPrint(); // person1
let bindPrint2 = bindPrint.bind(person2);
bindPrint2(); // person1! bind는 단 한번만 할 수 있다.

하지만 바이딩은 한번만 가능하기 때문에 주의해야 한다.

✅ setTimeout에서 bind 사용예제

let person ={
 name: "홍길동",
 age:25,
 hello: function(){
  setTimeout(function(){
   console.log(this)	// window 객체
   console.log(this.name)	//undefined
   console.log(this.age) 	//undefined
  },1000);
 },
};

person.hello();

이처럼 setTimeout함수에는 this가 기본값으로 window객체를 가리킨다. 

여기서 this를 person으로 바인딩 시켜주는 방법은 이러하다.

let person ={
 name: "홍길동",
 age:25,
 hello: function(){
  setTimeout(function(){
   console.log(this)	// person 객체
   console.log(this.name)	//홍길동
   console.log(this.age) 	//25
  }).bind(this),1000);
 },
};

person.hello();

hello 함수에서의 this는 person을 가리키기 때문에 setTimeout함수의 this를 바인딩 시켜준 모습이다.

4️⃣ 화살표 함수에서의 this

화살표 함수가 나오기 전까지는 함수가 어떻게 호출되는지에 따라 자신의 this값을 정의했습니다. 

하지만 화살표 함수는 자신을 포함하고 있는 외부 Scope에서 this를 계승받습니다.

✅ this범위 예

let person = {
  name: '짐코딩',
  printThis: () => {
	  console.log(this); // window 객체
	};,
};

여기서 외부 스코프는 window객체이기 때문에 this는 window객체를 반환한다.

let person = {
  name: '짐코딩',
  printThis: function () {
    setTimeout(() => {
      console.log(this); // person 객체
    });
  },
};

person객체 안에 화살표 함수가 있어서 setTimeout 의 외부 스코프는 person이 된다. 따라서 this의 값은 person 객체가 된다.

 

따라서 addEventListener 함수를 사용할 때에도 화살표 함수를 사용해 this를 선언하면 안된다.

❗조심하자❗

let btn = document.querySelector('button');  
button.addEventListener('click', () => {  
  console.log(this === window); // => true
  this.innerHTML = 'Clicked button';
});
// window객체가 반환되는 경우

let btn = document.querySelector('button');  
button.addEventListener('click', function() {  
  console.log(this === button); // => true
  this.innerHTML = 'Clicked button';
});
// button 요소가 반환되는 경우

6️⃣ Strict Mode 의 this

엄격 모드에서는 호출한 놈이 없을 경우 기본값을 window로 하지 않고 undefined로 합니다. 

더 엄격하게 검사하는 의미다.

✅ non strict mode

function printThis() {
  console.log(this);
}
printThis(); // window 객체

✅ strict mode

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