본문 바로가기
Frontend

JS this

by yongmin.Lee 2020. 11. 7.

this란?

- this는 기본적으로 실행 컨텍스트가 생성될 때 결정되므로, 어떤 방식으로 함수를 호출하느냐에 따라 this의 값이 달라진다

1. 전역공간에서의 this

- 전역 공간에서 this는 전역 객체를 가리킨다.
- 브라우저 환경에서 전역객체는 window이고, Node.js에서 전역객체는 global이다.

- 자바스크립트의 모든 변수는 특정객체(실행 컨텍스트의 LexicalEnvironment)의 프로퍼티로 동작하므로,  전역변수 a 와 전역컨텍스트에서 this.a 와 전역객체.a 는 모두 같은 값을 가진다.

2. 매서드로서 호출할 때, 매서드 내부의 this

- 함수와 메서드를 구분하는 유일한 차이는 독립성인데 함수는 그 자체로 독립적인 기능을 수행하며 메서드는 자신을 호출한 대상 객체에 관한 동작을 수행한다. -> this를 통해 함수와 메서드를 구분할 수 있다

- 어떤 함수를 메서드로서 호출하는 경우 호출 주체는 바로 함수명 앞의 객체이다.
- this에는 호출한 주체에 대한 정보가 담기므로 점 표기법의 경우 마지막 점 앞에 명시된 객체가 this이다.

3. 함수로써 호출 할 때, 함수 내부의 this

- 어떤 함수를 함수로서 호출할 경우에는 this가 지정되지 않으며, 실행 컨텍스트를 활성화할 당시에 this가 지정되지 않은 경우 this는 전역 객체를 바라본다.

4. 매서드의 내부함수로써 호출 할 때, 내부함수의 this

var obj1 = {
  outer: function () {
    console.log(this);
    var innerFunc = function () {
      console.log(this);
    };
    innerFunc(); // this = 전역객체(window)

    var obj2 = {
      innerMethod: innerFunc,
    };
    obj2.innerMethod(); // this = obj2
  },
};
obj1.outer(); // this = obj1

- this 바인딩에 관해서 함수를 실행할 당시의 주변 환경은 중요하지 않고, 오직 해당 함수를 호출하는 구문앞에 점(.) 또는 대괄호([]) 표기가 있는지 없는지가 중요하다. 점 또는 대괄호가 있으면 해당 함수는 메서드로 호출됬으므로 메서드의 객체가 this이고,  점 또는 대괄호 없으면 해당 함수는 함수로써 호출 됬으므로 this는 지정되지 않아 전역객체를 가리킨다

var obj1 = {
  outer: function () {
    var innerFunc = function () {
      console.log(this);
    };
    innerFunc(); // 전역객체(window)

    var self = this;
    var innerFunc2 = function () {
      console.log(self);
    };
    innerFunc2(); // obj1
  },
};
obj1.outer();

- 호출주체가 없을 때 자동으로 전역객체를 바인딩하지 않고 호출 당시 주변환경의 this를 그대로 상속 받고 싶을 때는 변수를 사용하면 된다!

5. 콜백함수 호출시, 콜백함수 내부의 thist

document.body.innerHTML += '<button id="a">클릭</button>';
document.body.querySelector("#a").addEventlistener("click", function (e) {
  console.log(this, e); // this = 앞서 지정한 엘리먼트
});

- 콜백 함수의 제어권을 가지는 함수(메서드)가 콜백 함수에서의 this를 무엇으로 할지를 결정하며, 특별히 정의하지 않은 경우에는 기본적으로 함수와 마찬가지로 전역객체를 바라본다.

6. 생성자 함수 내부의 this

var Cat = function (name, age) {
  this.bark = '야옹';
  this.name = name;
  this.age = age;
};
var choco = new Cat('초코', 7);
var nabi = new Cat('나비', 5);
console.log(choco, nabi);
/*
Cat { bark: '야옹', name: '초코', age: 7 }
Cat { bark: '야옹', name: '나비', age: 5 }
*/

- 생성자 함수 내부의 this는 클래스를 통해 만들어질 인스턴스를 참조한다.

bind 매서드

var func = function (a, b) {
  console.log(this, a, b);
};
var bindFunc = func.bind({ foo: "bar" }, 7);

func(1, 2);  // global객체 1 2
bindFunc(3); // {foo:"bar"} 7 3

- 앞서 다양한 상황에서 this에 바인딩되는 값이 달라지는 것을 확인하였지만, bind매서드를 이용하면 이러한 규칙을 깨고 this에 특정 값을 바인딩할 수 있다.

- bind 매서드는 넘겨 받은 this 및 인수들을 바탕으로 새로운 함수를 반환한다.

arrow function

- arrow function은 실행 컨텍스트를 생성할 때 this 바인딩 과정이 빠지고 스코프체인상 가장 가까운 상위 컨텍스트의 this를 계승받는다!

- 장점 : 상위 스코프의 this를 그대로 활용할 수 있다

- 단점 : 객체의 메소드를 정의시 arrow function을 사용하면 전역객체가 바인딩되므로 사용하면 안된다. 생성자 함수로 사용하면 안된다

callback function

- 콜백함수는 다른 코드의 인자로 넘겨주는 함수이다. 이때 콜백함수의 제어권도 같이 해당 코드에게 위임한다. 띠리서 콜백함수의 제어권을 위임받은 코드는 자체적인 내부 로직에 의해 콜백함수를 적절한 시점에 실행한다.

- 콜백함수도 함수이기 때문에 기본적으로 this가 전역객체를 참조하지만, 제어권을 넘겨받을 코드에서 콜백함수에 별도로 this가 될 대상을 bind 메서드로 지정한 경우에는 그 대상을 참조하게 된다.

'Frontend' 카테고리의 다른 글

JS 프로토타입  (0) 2020.11.07
JS 클로저  (0) 2020.11.07
JS 실행 컨텍스트  (0) 2020.11.07
JS 데이터 타입  (0) 2020.11.07
14. Redux-middleware  (0) 2020.11.06