[Javascript] this에 대해서

This


자바스크립트에서의 this는 c++에서의 this와는 다른 동작을 수행한다.

  • 일반적인 프로그래밍 언어에서 this는 자기 자신을 가리키는 참조 변수이다.
  • Javascript에서 this는 함수 호출 방식에 따라 this가 결정된다.

함수 호출 방식에 따라 다른 this

  • 함수 호출시 this : Window
  • 메소드 호출 시 this : 메소드 객체
  • 내부 함수 호출 시 this : window
  • 엄격 모드에서의 this : undefined
  • 이벤트 리스너 호출 시 this : 이벤트 새 객체
  • 생성자 함수 호출시 this : 생성된 새 객체

화살표 함수는 일반적인 this 바인딩과는 다르게 Lexical this(문맥적 this)를 가진다.

  • 화살표 함수 호출시 this : 함수 선언 시의 상위 스코프의 this

- 함수 호출시 this

자바스크립트에서 함수를 호출하면 해당 함수 내보 코드에서 사용된 this는 전역 객체 (window)에 바인딩된다.

함수는 전역객체의 메소드이다. 메소드 호출 시와 동일하게 메소드 객체를 this로 갖는다.

- 메소드 호출 시 this

객체의 메소드를 호출할 때는 해당 메소드를 호출한 객체로 바인딩된다.

prototype  객체도 메소드를 가질 수 있다. 일반적인 메소드의 this 바인딩 규칙을 따른다.

Prototype

  • 생성된 객체 Human.getName()호출시 this는 메소드를 호출한 객체인 Hyunbean 객체이다. 따라서 Hyunbean.name인 "Hyunbean"이 리턴된다.
  • prototype 객체인 getName()호출시의 this는 메소드를 호출한 객체인 Human.prototype객체이다. 따라서 "Suhyun"이 리턴된다.

- 내부 함수 호출 시 this

내부 함수도 함수 호출 시 this 바인딩 규약을 따른다. 즉 this  전역 객체에 바인딩된다.

  • 일반 함수, 메소드, 콜백 함수에 관계없이 해당 함수 내에 내부 함수는 전역 객체에 바인딩된다.
  • apply, call, bind 메소드를 통해서 this를 바인딩해서 사용할 수 있다.

- 엄격 모드에서의 this

엄격 모드는 코드 안정성과 오류 검증을 위해서 나온 것이다.

  • 엄격 모드에서 함수 실행 시 this는 undefined가 된다.
  • 내부 함수 호출 시 this 또한 undefined가 된다.
  • 의도치 않게 전역 객체에 바인딩된 this를 사용하는 것을 막을 수 있다.
    • null참조로 인해 죽기 때문에 의도치 않은 동작을 하는 것보다 쉽게 오류 검증을 할 수 있다.

- 이벤트 리스너 호출 시 this

이벤트 리스너에서의 this는 이벤트를 발생시킨 객체가 된다.

이벤트 리스너

console.log(this)는 getBtnId 객체를 가리키게 된다.

- 생성자 함수 호출 시 this

  • 자바스크립트 생성자 함수는 말 그대로 객체를 생성한다.
  • 다른 객체지향 언어의 생성자 함수와 달리 형식은 정해져 있지 않고 기존 함수에 new를 붙여서 호출한다.
  • 특정 함수가 생성자 함수로 정의되어 있음을 알리기 위해 첫 글자를 대문자로 하는 것을 권장한다.
자바스크립트 객체 생성 과정 new 연산자로 생성자 함수를  호출하는 과정.

1. 빈 객체 생성 및 this 바인딩

  • 빈 객체 성성 
    • 빈 객체란 자신을 생성한 함수의 prototype 프로퍼티가 가리키는 객체이다.
  • 생성된 객체는 this로 바인딩된다.
  • 따라서 이후 생성자 함수의 코드 내부에서 사용된 this는  빈 객체를 가리킨다.

2. this를 통한 프로퍼티 설정

  • 생성된 빈 객체에 this를 사용하여 동적으로 프로퍼티나 메소드를 생성할 수 있다.

3. 생성된 객체 리턴

  • 특별하게 정의된 리턴 문이 없는 경우 this로 바인딩된 새로 생성한 객체가 리턴된다.
  • 명시적으로 다른 객체를 리턴하도록 했다면 다른 객체가 리턴된다.
  • 객체가 아닌 값을 리턴하는 경우 this로 바인딩 된 새 객체가 리턴된다.
객체 리터럴 방식과 생성자 함수 방식의 차이
  • 생성자를 이용해 객체를 생성하는 방식과 리터럴을 이용해 생성하는 방식의 차이는 prototype 객체(proto)에 있다.
  • 위 예제에서 Hyunbean 객체의 프로토 타입은 Human이고 리터럴로 동일한 Hyunbean 객체를 만들면 그 객체의 프로토 타입 객체는 Object이다.
  • 이는 자바스크립트 객체 생성 규칙 때문이다. 자바스크립트 객체는 자신을 생성한 생성자 함수의 prototype 프로퍼티가 가리키는 객체를 자신의 프로토타입 객체로 설정하기 때문이다.
    • 객체 리터럴 방식에서는 객체 생성자 함수가 Object이고, Object.prototype
    • 생성자 함수 방식의 경우는 생성자 함수 자체가 프로토 타입 객체이다. Person.prototype
Scope-Safe Constructor Pattern
  • new를 사용하지 않고 생성자 함수를 호출 했을 때, 전역 객체가 프로퍼티가 할당되는 등 문제가 생길 수 있다.
  • 때문에 new를 쓰지 않고 객체를 생성하려 할 때 , new를 통해 생성하도록 강제해준다.

new 강제

- 화살표 함수 호출시 this

일반 함수와 화살표 함수의 가장 큰 차이점은 this이다.

  • 일반 함수의 this는 함수 호출시에 동적으로 바인딩된다.
  • 화살표 함수는 함수를 선언할 때, this에  바인딩 될 객체가 정적을 결정된다.
  • 화살표 함수의 this는  언제나 상위 스코프의 this를 가리킨다.
    • Lexical this를 가진다.
    • Lexcial scope와 비슷한 개념을 가진다.(함수의 상위 스코프를 결정하는 방식)
화살표 함수를 사용하면 안되는 경우

1. 객체의 메소드를 화살표 함수로 정의하는 경우 

  • 객체의 메소드를 화살표 함수로 정의하는 경우 메소드를 호출한 객체가 this가 되는것이 아니라 상위 스코프의 this인 전역 객체가 this가 된다.

ES6

  • 이런 경우에는 ES6의 축약 메소드 표현을 사용해야 한다.

ES6 축약

  • 클래스나 생성자 함수에서는 생성된 객체로 바인딩 되므로 사용이 가능하다.
    • 객체 생성시 this가 이미 생성된 객체로 바인딩 되어 있기 때문에 화살표 함수의 this는 생성된 객체로 바인딩된다.
  • 리터럴을 통해 객체를 생성하는 경우 주의해야 한다.

2. Prototype

  • 화살표 함수로 정의된 메소드를 prototype에 할당하는 경우, 객체의 메소드를 화살표 함수로 정의하는 경우와 같은 문제가 발생한다.
    • prototype 또한 객체이다.
    • 클래스,생성자 함수로 객체를 생성할 때 생성자 함수 내부에서 this로 할당하는 경우에는 문제가 없지만 아래와 같이 prototype 메서드로 정의하는 경우는 객체 생성시에도 제대로 this를 바인딩하지 못한다.
      • 전역객체가 바인딩 된다.

prototype

3. 생성자 함수

  • 화살표 함수는 생성자 함수로 사용할 수  없다.
  • 생성자 함수는 prototype 프로퍼티를 가지며 객체 생성시 프로토타입 링크를 형성한다.
    • prototype 프로퍼티는 prototype 객체를 가르키고, prototype 객체의 constructor는 생성자 함수를 가르킨다.
  • 화살표 함수는 prototype 프로퍼티를 가지고 있지 않다.

4. addEventListener 함수의 콜백 함수

  • 이벤트  객체를 this로 갖도록 하려면 일반 함수를 사용해야 한다.
  • 일반 함수는 이벤트 객체(current Target)을 this로 갖는다.
  • 화살표 함수는 전역 객체를 this로 갖는다.(생성될 때의 상위 스코프)

이벤트 객체

  • this를 고정시키고 싶을 때는 화살표 함수를 사용하면 된다.

 

참고 문서 -https://iamsjy17.github.io/javascript/2019/06/07/js33_15_this.html

 

Songlog

Javascript, Typescript, Angular, React, RxJS, etc.

iamsjy17.github.io

 

'개발' 카테고리의 다른 글

[Javascript] 디자인 패턴 - 싱글톤 패턴  (0) 2021.08.30
[Javascript] document.Selection 과 Range 정리  (0) 2021.08.16
[Javascript] Ajax  (0) 2020.12.31
[Javascript] 이벤트 - 2  (0) 2020.12.31
[Javascript] 이벤트  (0) 2020.12.30
<