자바스크립트 컨텍스트 바인딩 (this)

Doum Kim·2020년 7월 21일
0

Javascript

목록 보기
21/23
post-thumbnail
post-custom-banner

자바스크립트의 컨텍스트 바인딩에 대해서 이야기 해보려고 한다.

자바스크립트를 공부하다 보면 항상 this가 무엇일까 고민을 하게 만드는 순간이 있다.
그런 고민을 줄여줄 this가 결정되는 5가지 요인들을 알아보자.

1. 기본 바인딩
2. 암시적 바인딩
3. 명시적 바인딩
4. new 연산자 바인딩
5. 예외

기본 바인딩

function foo() {
  console.log(this.name);
}

let name = 'kim';

foo(); // 'kim'

함수 선언식을 사용하면 this는 전역객체와 바인딩이 된다. 단, 엄격 모드에서는 에러가 발생한다.

암시적 바인딩

function foo() {
  console.log(this.name);
}

const obj = {
  name:'lee'
  foo:foo
};

obj.foo(); // 'lee'

함수 호출시 객체의 프로퍼티로 접근해 실행하는 암시적 바인딩이다.
객체 obj의 프로퍼티 foo에 foo라는 함수의 참조를 할당하고 객체를 통해 foo를 호출하면 객체를 바인딩하는 규칙을 갖는다.

function foo() {
  console.log(this.name);
}

const obj = {
  name:'lee'
  foo:foo
};

bar = obj.foo;

name = 'kim';

bar(); // 'kim'

단, 위의 코드와 같이 bar에 참조를 저장하면 일반 함수로 바뀐다. 즉 기본 바인딩 규칙을 따르게 되며 this는 전역 컨텍스트에 바인딩 된다.

명시적 바인딩

자바스크립트의 call, apply, bind 내장 함수를 사용해 명시적으로 바인딩 할 컨텍스트를 정해줄 수 있다.

function foo() {
  console.log(this.name);
}

const obj = {
  name:'lee'
};

foo.call(obj); // 'lee'

new 연산자 바인딩

우리가 class나 생성자 함수를 이용해 인스턴스를 만들어낼 때 new 연산자를 사용한다.
이 연산자는 생성자 함수 내에서 정의한 this가 인스턴스에 바인딩이 되도록 만들어 준다.

function User(name) {
  this.name = name;
  this.hello = function(){
    console.log(this.name);
  }
}

const user1 = new User('kim');

user1.hello() //'kim'

예외 사항

ES6 문법인 화살표 함수와 setTimeout 콜백 함수의 예외 사항을 살펴보자.

setTimeout의 콜백함수는 setTimeout이 호출하기 때문에 setTimeout에 의존적이다.
따라서 콜백함수의 this는 전역 객체로 바인딩 된다.

function hello() {
  setTimeout(function callback(){ console.log(this.name) })
}

const obj = {
  name: 'Kim',
  hello: hello
};

const name = 'Lee'

hello(); // 'Lee'
obj.hello(); // 'Lee'
hello.call({name: 'chris'}); // 'Lee'

위에서 설명한 규칙들은 실행 시점에서 바인딩 규칙이 적용된다. 따라서 동적 바인딩이라고 할 수 있다.
반면 화살표 함수는 기존의 컨텍스트 바인딩 규칙을 따르지 않는다. 따라서 정적 바인딩이라고 한다.
코드상 상위 블록의 컨택스트를 this로 바인딩 한다.

function hello() {
  setTimeout(() => { 
    console.log(this.name) 
  })
}

const obj = {
  name: 'Kim',
  hello: hello
};

const name = 'Lee'

hello(); // 'Lee'
obj.hello(); // 'Kim'
hello.call({name: 'Choi'}); // 'Choi'

바인딩 우선순위

new 바인딩 > 명시적 바인딩 > 암시적 바인딩 > 기본바인딩

참고 - 김정환 블로그

post-custom-banner

0개의 댓글