[JavaScript] this

Joowon Jang·2024년 7월 3일

JavaScript

목록 보기
5/17

this?

JavaScript에는 this라는 특별한 키워드가 있다.
다른 객체지향 언어에서의 this는 보통 클래스로 생성한 인스턴스 객체를 의미하고, 클래스에서만 사용할 수 있다. 하지만, JavaScript에서는 어디서든 this를 사용할 수 있고, 상황에 따라 this가 달라지기 때문에 많은 혼란을 준다.

실행 컨텍스트와 this

this는 어떤 실행 컨텍스트가 생성될 때, 실행 컨텍스트의 환경 객체를 구성하는 3가지 요소 중 하나이다.

  • variableEnvironment
  • lexicalEnvironment
  • thisBinding

JavaScript에서 함수를 호출할 때 실행 컨텍스트가 생성되기 때문에 함수를 호출할 때 this가 결정된다고 할 수 있다.

실행 컨텍스트 - 참고
https://velog.io/@juwon98/JavaScript-execution-context

일반적인 this 바인딩 규칙

일반적인(this를 명시적으로 바인딩하지 않은) 경우, 아래와 같은 규칙에 따라 this가 결정된다.

  • 전역공간에서의 this는 전역객체(window, global, globalThis)를 참조한다.

console.log(this); // window
  • 어떤 함수를 메서드로서 호출한 경우 this는 메서드 호출 주체(메서드명 앞의 객체)를 참조한다.

var obj = {
  method: function() {
    console.log(this);
  }
};

obj.method(); // obj
  • 어떤 함수를 함수로서 호출한 경우 this는 전역객체를 참조한다. 메서드의 내부함수에서도 같다.

function f1() {
  console.log(this);
}

f1(); // window

메서드의 내부함수

var obj = {
  outerF: function() {
    console.log(this);
    
    function innerF() {
      console.log(this);
    }
    innerF(); // window
  }
};

obj.outerF(); // obj

ES6에서 this를 바인딩하지 않는 화살표 함수가 등장했다.
화살표 함수 내부에는 this가 존재하지 않기 때문에, 스코프체이닝에 의해 가장 가까운 this를 찾는다.

var obj = {
  outerF: function() {
    console.log(this);

    var innerF = () => {
      console.log(this);
    };
    innerF();
  }
};

obj.outerF(); // obj obj

추가 예시

var obj = {
  F: () => {
    console.log(this);
  }
};

obj.F(); // window
  • 콜백 함수 내부에서의 this는 해당 콜백 함수의 제어권을 넘겨받은 함수가 정의한 바에 따르며, 정의하지 않은 경우에는 전역객체를 참조한다.

setTimeout(function() {
  console.log(this); // window
}, 1000);
/* setTimeout의 콜백함수는 this가 정의되지 않음 */

document.body.innerHTML += '<button id="btn" type="button">버튼</button>';
var btn = document.getElementById('btn');

btn.addEventListener('click', function(e) {
  console.log(this, e); // btn, Event
});
/* addEventListener의 콜백함수는 this가 btn */
  • 생성자 함수에서의 this는 생성될 인스턴스를 참조한다.

var Food = function(name, price) {
  this.eatable = true;
  this.name = name;
  this.price = price;
}

var apple = new Food('사과', 3000);
var chocolate = new Food('초콜릿', 1500);

console.log(apple, chocolate);

/* 결과
Food {eatable: true, name: '사과', price: 3000}
Food {eatable: true, name: '초콜릿', price: 1500}
*/

명시적 this 바인딩

  • call, apply 메서드는 this를 명시적으로 지정하면서 함수 또는 메서드를 호출한다.

function func(a, b, c) {
  console.log(this, a, b, c);
}

func.call({x:'test'}, 1, 2, 3); // {x:'test'} 1 2 3
func.apply({x:'test'}, [1, 2, 3]); // {x:'test'} 1 2 3
  • bind 메서드는 this 및 함수에 넘길 인수를 일부 지정해서 새로운 함수를 만든다.

function func(a, b, c) {
  console.log(this, a, b, c);
}

var newFunc = func.bind({x:'new'});
newFunc(1,2,3); // {x:'new'} 1 2 3
  • 요소를 순회하면서 콜백 함수를 반복 호출하는 내용의 일부 메서드는 별도의 인자로 this를 받기도 한다.

    (forEach, map, filter 등)
var obj = {
  sum: 0,
  add: function() {
    [1,2,3,4].forEach(function(item) {
      this.sum += item;
    },this); // add 메서드의 this(obj)를 전달
  }
}

obj.add();
console.log(obj.sum); // 10
profile
깊이 공부하는 웹개발자

0개의 댓글