
1. this가 함수 그 자체를 가리킨다는 것은 오해이다.
this는 이름 그 자체로 이해하면 안된다.
function foo(num){
console.log("foo " + num);
this.count++ //추가된 프로퍼티와는 다른 객체이다.
}
//foo라는 함수 객체에 count 프로퍼티가 추가
foo.count = 0;
for (let i=0; i<10; i++){
if(i>5){
foo(i);
}
}
console.log(foo.count)
/* Console :
"foo 6"
"foo 7"
"foo 8"
"foo 9"
0
*/
this.count에서 this는 함수 객체를 바라보는 것이 아니다. 프로퍼티 명이 똑같아서 헷갈릴 수 있지만 근거지를 둔 객체 자제가 다르다.
** this는 자기 참조를 할 수 없다. **
여기서 생각해바야할 점 : 왜 this 참조가 이상하게 이루어졌을까?
-> 증가한 count는 전역변수 count이다.
** 주의해야할 점** : this에 대해 피하거나 다른 객체로 옮기는 등 lexical scope를 이용하는 방식은 지양해야한다. this의 작동원리에 대한 제대로 된 이해가 필요하다.
foo함수 객체를 직접 가리키도록 강제하여 this를 적용하면 앞의 코드는 아래와 같다.
function foo(num){
console.log("foo " + num);
this.count++ //추가된 프로퍼티와는 다른 객체이다.
}
//foo라는 함수 객체에 count 프로퍼티가 추가
foo.count = 0;
for (let i=0; i<10; i++){
if(i>5){
foo.call(foo, i);
//call()함수를 호출했기때문에, 여기서 this는함수 객체 'foo'자신을 가리킨다.
}
}
console.log(foo.count)
/* Console :
"foo 6"
"foo 7"
"foo 8"
"foo 9"
4
*/
2. this가 함수의 scope를 가리킨다는 말은 잘못된 이해이다.
this는 어떤 식으로도 함수의 렉시컬 스코프를 참조하지 않다는 사실은 분명하다.
내부적으로 스코프는 별개의 식별자가 달린 프로퍼티로 구성된 객체의 일종이나,
스코프 '객체' 자체는 js 구현체인 엔진의 내부 부품이기 때문에 일반 JS코드로 접근이 불가능하다.
렉시컬 스코프 참조와 this는 엄연히 다르다.
서로 다른 함수의 내부 스코프에 접근할 때 this 레퍼런스로 참조하는 것 자체가 불가능하다.
** this가 함수의 렉시컬 스코프를 가리킬 수 없다는 것이다. **
this의 작동 원리
- this는 작성 시점이 아닌 런타임 시점에서 바인딩되며, 함수 호출 당시 상황에 따라 콘텍스트가 결정된다. 함수 선언 위치와 상관 없이 this 바인딩은 오로지 어떻게 함수를 호출했느냐에 따라 정해진다.
- 어떤 함수를 호출했을 시, Activation Record(활성화 레코드), 즉 실행 콘텍스트가 만들어진다.
- 실행 콘텍스트에는 함수가 호출된 근원(Call-staack 과 호출 방법, 전달된 인자 등의 정보가 담겨있다.
- this 레퍼런스는 그중 하나로, 함수가 실행되는 동안 이용할 수 있다.
정리
this는 함수 자신이나 함수의 렉시컬 스코프를 가리키는 레퍼런스가 아니다.
** 실제로 함수 호출 시점에 바인딩 되며 무엇을 가리킬지는 전적으로 함수를 호출한 코드에 달렸다. **
'JavaScript' 카테고리의 다른 글
| 함수형 프로그래밍 패러다임의 좋은 코딩 습관 (0) | 2023.03.11 |
|---|---|
| [YOU DON'T KNOW JS] Chapter2. Call-Site(함수 호출부) (0) | 2022.08.17 |
| [JavaScript] DataType (0) | 2022.08.17 |
| [JavaScript] Variable (0) | 2022.08.17 |
| [Learning React] Chapter2. JavaScript for React.js (0) | 2022.08.14 |