this

Taek·2020년 8월 6일
3
post-thumbnail

JavaScript의 헷갈리는 개념 중 하나인 this

호출되는 시점과 상황에 따라 값이 달라져 디버깅을 유발하는 키워드다.

그간 삽질한 경험과 학습(Javascript 핵심 개념 알아보기 - JS Flow)을 바탕으로 this에 어떤 값이 바인딩 되는지 간략하게 정리했다.


# 전역공간

전역공간에서 this는 window(global) 객체

// 전역공간
console.log(this); // Window {parent: Window ... }

# 함수내부

함수내부에서 this는 window(global) 객체

함수를 전역객체의 메소드라 생각하면 코드상 this를 파악하기 용이하다. (아래 메소드 호출 시 this 참고)

// 함수내부
function foo() {
  console.log(this);
}
foo(); // Window {parent: Window ... }
// 함수의 함수내부
function foo() {
  function bar() {
    console.log(this);
  }
  bar();
}
foo(); // Window {parent: Window ... }
// 메소드의 함수내부
const obj = {
  a: function() {
    function b() {
      console.log(this);
    }
    b();
  }
}
obj.a(); // Window {parent: Window ... }

# 메소드 호출

메소드 호출 시 this는 메소드 호출 주체

// 메소드 호출
const obj = {
  a: function() {
    console.log(this);
  }
}
obj.a(); // {fn: ƒ}
// 메소드 호출
const obj = {
  a: {
    b: function() {
      console.log(this);
    }
  }
}
obj.a.b(); // {b: ƒ}

화살표 함수에는 함수 이름, this, arguments가 없다. 따라서 예제 코드를 화살표 함수로 바꾸면 스코프 체인에 따라 global 객체가 this 바인딩 된다.
ES6 화살표 함수에 없는 3가지?

// 화살표 함수 호출
const obj = {
  a: () => {
    console.log(this);
  }
}
obj.a(); // Window {parent: Window ... }

# 콜백 함수

콜백 함수에서 this는 기본적으로 함수내부에서와 동일하다.

하지만 언급했던 것 처럼 상황에 따라 this 값이 달라지는데 가장 흔한 경우가 콜백 함수안에 쓰인 this 이다.


1. call, apply, bind 메서드를 통해 명시적인 this 바인딩 한 경우와 그렇지 않은 경우

// this 바인딩
const callback = function() {
  console.log(this);
}
const obj = {
  a: 1,
  b: function(cb) {
    cb();
    // cb.call(this); // {a: 1, b: ƒ}
  }
}
obj.b(callback.bind(obj)); // {a: 1, b: ƒ}
setTimeout(callback.bind(obj), 100); // {a: 1, b: ƒ}
// this 바인딩 하지 않은 경우
const callback = function() {
  console.log(this);
}
const obj = {
  a: 1,
  b: function(cb) {
    cb();
  }
}
obj.b(callback); // Window {parent: Window ... }
setTimeout(callback, 100); // Window {parent: Window ... }

2. 이벤트 리스너

addEventListener 콜백 함수의 this는 내부 규칙으로 인해 event 객체의 currentTarget으로 바인딩 된다.

// 이벤트 핸들러
document.querySelector('body').addEventListener('click', function() {
	console.log(this); // <body>...<body>
});
// 하지만 this를 명시적으로 대체한 경우
const obj = { a: 'a' };

document.querySelector('body').addEventListener('click', function() {
	console.log(this); // {a: "a"}
}.bind(obj));

0개의 댓글