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 바인딩 규칙을 따른다.
- 생성된 객체 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를 통해 생성하도록 강제해준다.
- 화살표 함수 호출시 this
일반 함수와 화살표 함수의 가장 큰 차이점은 this이다.
- 일반 함수의 this는 함수 호출시에 동적으로 바인딩된다.
- 화살표 함수는 함수를 선언할 때, this에 바인딩 될 객체가 정적을 결정된다.
- 화살표 함수의 this는 언제나 상위 스코프의 this를 가리킨다.
- Lexical this를 가진다.
- Lexcial scope와 비슷한 개념을 가진다.(함수의 상위 스코프를 결정하는 방식)
화살표 함수를 사용하면 안되는 경우
1. 객체의 메소드를 화살표 함수로 정의하는 경우
- 객체의 메소드를 화살표 함수로 정의하는 경우 메소드를 호출한 객체가 this가 되는것이 아니라 상위 스코프의 this인 전역 객체가 this가 된다.
- 이런 경우에는 ES6의 축약 메소드 표현을 사용해야 한다.
- 클래스나 생성자 함수에서는 생성된 객체로 바인딩 되므로 사용이 가능하다.
- 객체 생성시 this가 이미 생성된 객체로 바인딩 되어 있기 때문에 화살표 함수의 this는 생성된 객체로 바인딩된다.
- 리터럴을 통해 객체를 생성하는 경우 주의해야 한다.
2. Prototype
- 화살표 함수로 정의된 메소드를 prototype에 할당하는 경우, 객체의 메소드를 화살표 함수로 정의하는 경우와 같은 문제가 발생한다.
- prototype 또한 객체이다.
- 클래스,생성자 함수로 객체를 생성할 때 생성자 함수 내부에서 this로 할당하는 경우에는 문제가 없지만 아래와 같이 prototype 메서드로 정의하는 경우는 객체 생성시에도 제대로 this를 바인딩하지 못한다.
- 전역객체가 바인딩 된다.
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
'개발' 카테고리의 다른 글
[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 |