[JS] This의 Binding 5가지

Chipmunk_jeong·2021년 8월 3일
0

TIL

목록 보기
56/62
post-thumbnail

해당 블로깅은 인프런의 강의를 들으며 공부한 내용을 정리한 글입니다.
ES5 기준 핵심 내용을 공부하면서 작성하는 블로깅

This Binding이 일어나는 시점은?

  • 실행 컨텍스트가 활성화 될 때 바인딩이 발생한다
  • 컨텍스트에 대한 게시글은 앞의 게시물에서 정리했다.
  • 실행 컨텍스트는 해당 컨텍스트를 지닌 함수가 호출될 때 실행

그렇다면 해당 컨텍스트를 지닌 함수를 어떻게 호출하냐에 따라 This가 바인딩되는 대상이 다르다.

  1. 전역공간에서의 this
  2. 함수 호출시의 this
  3. 메서드 호출시의 this
  4. callback호출시의 this
  5. 생성자함수(constructor)호출시의 this

위처럼 실행컨텍스트가 호출되는 방법에 따라 this는 다르게 바인딩이 된다.

전역에서 호출시


this는 전역객체를 가르킨다.
브라우저에서는 window 노드에서는 globalthis가 된다.

윈도우 객체

글로벌 객체

함수 호출시


함수 호출했을 때에도 this는 전역 객체를 가르킨다.
왤까?? 함수는 전역공간에서 호출을한다. 그렇다면 함수에서 this는 전역공간에서의 this가 될것이고 전역 공간의 this는 전역 객체이기 때문이다.

함수로써 호출했을 때의 this


여기서 함수 내부에서 또 다른 내부함수를 정의하여 해당 내부 함수에서 console을 확인했을때도 this는 전역 객체가 나온다. 이것은 창시자의 실수 또는 자바스크립트의 성격이라고 볼 수 있으며, ES6에서는 arrow function문법이 존재하고, 바인딩을 하지않으면 바로 위에있는 컨텍스트의 this를 가져온다. 하지만,
ES5의 환경(함수 선언식)에서 함수로써 호출되었을 때 this는 전역객체가 된다.

메서드 내에서 함수로 호출 할 때의 this

var test = {
  a: function() {
    function b() {
      console.log(this);
    }
    b();
  }
}
test.a();

위를 호출하면 this는 전역 객체이다.
this를 출력하는 것은 b라는 이름을 가진 함수이다.
ES5환경에서 함수로 호출은 this가 전역 객체를 의미한다.
this가 바인딩 될때 호출되는 방법이 어떤지를 보면 쉽게 확인할 수 있다.

메서드 호출시


메서드로 호출시에는 this가 바인딩 되는 대상은 메서드를 호출하는 대상이 this로 바인딩 된다.(a.b()라고 했을때 b메서드를 호출하는 a객체가 this가 된다)

1)a객체의 메서드를 호출시 메서드에서 thisa가 된다.

2)a객체 안의b객체의 메서드인c를 호출하면 메서드에서this.c()앞의 b객체가 된다.

내부 함수에서 this 우회법


var a = 10;
var obj = {
  a: 20,
  b: function() {
    console.log(this.a);
   
    function c() {
      console.log(this.a);
    }
    c();
  }
}
obj.b();

콘솔에서 가르키는 this.a는 각각 20과 10이 출력된다.
그 이유는 obj.b()를 호출할때 this는 메서드로써 호출됨으로 호출하는 객체가 this가 되어 obj.a인 20을 출력한다.
하지만 c()에서 호출하는 this는 메서드가 아닌 함수로써 호출임으로 this는 전역객체가 된다. 그래서 window.a를 출력하게 되고, 특이하게 전역객체서 선언된 var a의 값인 10을 출력한다. 이 부분은 자바스크립트의 특이성인데 전역 컨텍스트에 선언된 변수는 전역 객체의 프로퍼티가 된다.

그럼 여기 내부함수에서 thisb와 같이 obj라는 객체를 가르키기 위해서 어떤방법을 사용하면 좋을까?

var a = 10;
var obj = {
  a: 20,
  b: function() {
    var self = this;  // 여기서 self라는 변수에 this맵핑
    console.log(this.a);
   
    function c() {
      console.log(self.a); // 맵핑된 self변수를 통해 출력
    }
    c();
  }
}
obj.b();

위 처럼 this를 내부에서 다른 변수에 맵핑을 하여 해당 변수를 이용하면 내부 함수에서도 호출을 할 수 있다.

콜백함수 호출시


콜백함수에서 this는 여러가지가 있지만, 기본적으로는 전역객체를 바인딩한다고 생각하면 된다. 하지만 call, apply, bind 메서드를 통해 this를 바인딩 한다면, 전역객체가 아닌 바인딩 되는 다른 무언가가 this가 될것이다.

var callback = function() {
  console.dir(this);
};
var obj = {
  a: 1,
  b: function(cb) {
  	cb();
  }
};
obj.b(callback);

위에서의 this는 전역객체이다.
앞에서 다 알아봤듯이 cb를 실행하는 시점에서는 그냥 함수를 실행한 것이고, ES5에서는 함수를 실행할때 this는 전역객체이다.
그래서 콜백함수로 호출이 되어도 기본적으로 this는 전역객체지만

var callback = function() {
  console.dir(this);
};
var obj = {
  a: 1,
  b: function(cb) {
  	cb.call(this);
  }
};
obj.b(callback);

위에서 매개변수로 입력받은 콜백함수를 call메서드를 통해서 thisobj로 바인딩해주고 호출을 한다.
b라는 메서드 내에서 thisobj이기 때문이다.
이처럼 this를 바인딩을 따로 해주지 않는 이상 전역객체를 바라본다.

마지막으로 setTimeout에서의 this바인딩 예제를 보자.

var callback = function() {
  console.dir(this);
};
var obj = {
  a: 1
};
setTimeout(callback, 100);

위의 코드에서 callback함수가 호출되면 콘솔에는 window 전역객체가 찍힌다.


하지만 callback함수의 thisobj로 바인딩해준다면?

var callback = function() {
  console.dir(this);
};
var obj = {
  a: 1
};
setTimeout(callback.bind(obj), 100);

위 처럼 thisobj로 바인딩되어 찍힌다.

생성자함수 호출시


생성자는 new키워드를 통하여 새로운 인스턴스를 생성할때 호출된다.
이 때는 새로 생성되는 인스턴스 자체가 this가 된다.

function Person(name, age) {
  this.name = name;
  this.age = age;
}
var quokka = new Person('quokka', 29);
console.log(quokka);

위 코드를 실행할 때 Personthisnew키워드를 통해서 인스턴스를 생성할때 생성자로 호출되기때문에 this가 생성되는 인스턴스인 quokka가 되고 내부에서 quokka.name = 'quokka', quokka.age = 29로 지정이 되는것이다.

profile
Web Developer

0개의 댓글