* 해당 글은 코어자바스크립트 강의를 들으며 정리한 내용입니다.
ThisBinding
This는 실행 컨텍스트가 활성화될 때 Binding 된다.
그리고 실행 컨텍스트는 함수가 호출될 때 생성된다.
따라서, ThisBinding은 함수가 호출될 때 결정된다.(동적으로 this가 Binding된다.)
- 함수가 호출될 때 결정된다.
- 다음 다섯 가지 방식에 따라 결정된다.
- 전역공간에서
- 함수 호출시
- 메서드 호출시
- callback 호출시
- 생성자 함수 호출시
- 다음 다섯 가지 방식에 따라 결정된다.
1. 전역공간에서의 this
- 전역 객체(host 객체)를 가리킨다.
- 런타임(host)에 따라 전역 객체의 정보가 달라진다.
- window(브라우저) / global(nose.js)
2. 함수 호출시
- 일반 함수
- 전역 객체를 가리킨다.
(자바스크립트 설계 오류라는 의견과 특성이라는 의견으로 나뉜다고 한다.)
- 전역 객체를 가리킨다.
- 화살표 함수
- 바로 위에 있는 실행 컨텍스트의 this를 가리킨다.
3. 메소드 호출시
- b함수를 a객체의 a '메소드'로서 호출시, b 함수의 this는 자신을 호출한 a를 가리킨다.
- 위 내용의 코드는 a.b(); 로 작성되는데, 호출되는 메소드 앞에 점이 있으면 그 앞 객체가 this이다.
- a.b.c(); 의 경우에는 c의 앞에 있는 a.b가 this이다.(대괄호 표기법도 마찬가지다)
💡 메소드?
평범한 함수지만, 어떤 객체에 속해있으면 '메소드'라고 부른다. 이는 인스턴스(객체)와 관련된 내용이다. 객체지향 프로그래밍에서는 클래스의 인스턴스에 포함된 함수는 인스턴스와 관련된 동작을 하는 함수이므로 '메소드'라 부른다. 자바스크립트에서는 해당 개념을 확장시켜 인스턴스 뿐만 아니라 모든 객체에 속한 함수를 '메소드'라 부른다.
3-1. 메소드 내부에서 함수 호출시 this 우회하는 법
let a = 10;
let obj = {
a: 20,
b: function() {
console.log(this.a);
function c() {
console.log(this.a);
}
c();
}
}
obj.b();
위 코드를 실행하게 되면, b()함수 실행 시에는 this가 obj를 가리키고, c() 함수 실행 시에는 전역 객체를 가리키게 된다. (위 내용 2번-함수 호출시, 3번-메소드 호출시 참고) 따라서 5L 결과는 20, 8L 결과는 10이 나온다.(이는 즉, 전역 변수로 선언된 a가 전역 객체의 프로퍼티로 동작 한다는 뜻이다. 이 또한 자바스크립트 설계의 오류라는 의견이 많다.)
만약, c() 함수 내부의 this가 obj를 바라보게끔 하려면 어떻게 해야 할까?
3-1-1. ES5 call / apply
...
b: function() {
console.log(this.a);
function c() {
console.log(this.a);
}
c.call(this);
}
...
- 명시적인 this 바인딩 명령을 사용하여 this 자체를 다른 값으로 덮어씌운다.
3-1-2. 다른 변수를 사용한다.(스코프 체인 활용)
...
b: function() {
let self = this;
console.log(this.a);
function c() {
console.log(self.a);
}
c();
}
...
위와 같이 내부 함수(c) 상위에 self라고 하는 변수에 this를 담아서 해결할 수도 있다. 이 코드는 다음 과정을 거쳐 동작한다.
- c() 함수 호출 시, 자신의 LexicalEnvironment에서 self를 찾는다.
- 못 찾았으므로, outerEnvironmentReference를 타고 외부(b 함수)에 있는 LexicalEnvironment에서 self를 찾는다.
- 해당 self는 앞서 들어온 this인 obj를 가리키고 있다.
3-1-3. ES6 Arrow function(화살표 함수) 사용
화살표 함수는 this를 바인딩하지 않는다. 따라서, 스코프 체인을 따라 상위에 있는 this에 접근하여 사용한다.
즉, 위 코드에서 c 함수를 화살표 함수로 변경하면, this가 상위 함수 b의 this를 가리키므로 결국 obj를 가리키게 된다.
4. callback 호출시
- 기본적으로는 함수 내부와 동일하다.
5. 생성자함수 호출시
+ 추가
call, apply, bind 메소드
function a (x, y, z) {
console.log(this, x, y, z);
}
let b = {
bb: 'bbb'
};
a.call(b, 1, 2, 3);
a.apply(b, [1, 2, 3]);
let c = a.bind(b);
c(1, 2, 3);
let d = a.bind(b, 1, 2);
d(3):
참고자료
코어자바스크립트
'Language > JavaScript' 카테고리의 다른 글
| [JS] Promise 동작 원리 (0) | 2023.06.17 |
|---|---|
| [JS] 프로토타입-1 (prototype) (0) | 2023.03.21 |
| [JS] 모듈화와 스코프 (0) | 2023.02.22 |
| [JS] 함수 선언문 vs 함수 표현식 (ft. 호이스팅) (2) | 2023.02.21 |
| [JS] Execute context(실행 컨텍스트)와 scope 기초 (0) | 2023.02.21 |