[YOU DON'T KNOW JS 정리] THIS (1)
[YOU DON'T KNOW JS 정리] THIS (1)
자바스크립트에서 가장 헷갈리는 개념 중 하나가 this 키워드이다.
this는 모든 함수 scope 내에 자동으로 설정되는 특수한 식별자이다.
경험이 많은 js개발자도 this가 무엇을 가리키는지 정확히 파악하는건 힘든일이니.
모른다고 부끄러워 하지말고 정확하게 공부해보자.
1.1 this 가 필요한 이유
일단 this가 "무엇을 가르키는지" 보다 "왜" 필요한 지부터 살펴보자.
⇒ this 의 유용함과 필요성을 먼저 파악해보자.
identify() {
return this.name.toUpperCase();
}
function speak() {
var greeting = `Hello ${identify.call(this)}`;
console.log(greeting);
}
var me = {
name: "Kyle"
};
var you = {
name: "Reader"
};
identify.call(me); // "KYLE"
identify.call(you); // "READER"
speak.call(me); // "Hello Kyle"
speak.call(you); // "Hello Reader"
identify()
와 speak()
두 함수는 객체 별로 따로 함수를 작성할 필요 없이
객체 me
와 you
모두에서 재사용 할 수 있다.
function identify(context) {
return context.name.toUpperCase();
}
function speak(context) {
var greeting = `Hello ${identify(context)}`;
console.log(greeting);
}
identify(you); // "READER"
speak(me); // "Hello Kyle"
- this와 call 메서드를 사용하지 않고 함수에 context를 명시하는 방법도 있다.
- 하지만 암시적인 객체 레퍼런스를 함께 전달하는(Passing Along) this 체계가 API 설계상 좀 더 깔끔하고 명확하며 재사용하기 쉽다.
- 사용 패턴이 복잡해질수록 보통 명시적 인자로 context를 넘기는 방법이 this 콘텍스트를 사용하는 것보다 더 지저분해지는 경향이 있다
1.2 헷갈리는 것들
'this' 를 이름 자체 글자 그대로 생각하지 말자.
1.2.1 This 에 대한 오해 (1) - 자기 자신
this는 함수 그 자체를 가리킨다?
→ 이것은 그럴싸한 문법적 추론이다. 틀렸다.
함수가 this로 자기 참조를 할 수 없다는 걸 증명하기 위한 예제
function foo(num) {
console.log("foo : ", numm);
// 'foo' 가 몇 번 호출됐는지 추적
this.count++;
}
foo.count = 0;
var i;
for(var i=0; i<10; i++) {
if(i > 5) {
foo(i);
}
}
console.log(foo.count); // 0
foo.count = 0
으로foo
라는 (함수) 객체에 값이 0 인count 프로퍼티
가 추가 된다.- 함수
foo
내부에this.foo
의 this 는 함수 foo 를 가리킬 꺼라 생각하지만 그렇지 않다. - 결국
this.count
가foo.count
가 아니므로 초기 선언한0
에서 값이 증가하지 않는다
this 원리를 파악하지 않고 이슈를 피하기 위한 우회책
function foo(num) {
console.log("foo : ", numm);
// 'foo' 가 몇 번 호출됐는지 추적
data.count++
}
var data = {
count: 0
};
var i:
for(var i=0; i<10; i++) {
if(i > 5) {
foo(i);
}
}
console.log(foo.count); // 4
이렇게 this 를 명시적인 객체로 변경하여, 문제를 해결할 수도 있지만
이는 작동원리는 모르는 채 렉시컬 스코프(Lexical Scope) 라는 편리한 장치에 몸을 맡긴 셈이다.
Lexical Scope를 사용하지 말라는 게 아니라,
회피하지 말고 this의 정확한 동작 원리를 파악하자.
function foo() {
foo.count = 4; // 'foo' 는 자기 자신을 가리킨다
}
setTimeout(function() {
// 익명 함수는 자기 자신을 가리킬 방법이 없다.
}, 1000);
arguments.callee
로 실행 중인 함수 객체를 가리킬 수 있지만, 지금은 Deprecated 된 레퍼런스이니 사용하지 말자.
자기 참조가 필요할 경우 익명 함수 를 사용하기 보단 기명 함수(함수 표현식)를 사용하는 게 최선이다.
function foo(num) {
console.log("foo : ", numm);
// 'foo' 가 몇 번 호출됐는지 추적
foo.count++
}
foo.count = 0
var i:
for(var i=0; i<10; i++) {
if(i > 5) {
foo(i);
}
}
console.log(foo.count); // 4
this.count
를foo
의 렉시컬 스코프를 사용하여 원하는 방식으로 동작하게 수정하였다.- 하지만 이 역시 this를 제대로 이해하지 않은 채 문제를 회피하는 방식이다.
function foo(num) {
console.log("foo : ", numm);
// 'foo' 가 몇 번 호출됐는지 추적
this.count++;
}
foo.count = 0;
var i;
for(var i=0; i<10; i++) {
if(i > 5) {
// 'call()' 메서드로 호출
// 'this' 는 이제 확실히 함수 객체 'foo' 자신을 가리킨다
foo.call(foo, i);
}
}
console.log(foo.count); // 4
- call 메서드
로 this 로 참조된 foo
를 명시적으로 설정하였다.
1.2.2 자신의 스코프
this가 함수의 스코프를 가리킨다는 것은 흔한 오해
→ this는 어떤 식으로도 함수의 렉시컬 스코프를 참조하지 않는다.
스코프는 내부적으로 별개의 식별자가 달린 프로퍼티로 구성된 객체의 일종이지만, 스코프 '객체'는 자바스크립트 구현체인 '엔진'의 내부 부품이기 때문에 일반 자바스크립트 코드로는 접근하지 못한다.
this로 함수의 렉시컬 스코프를 가리키록 시도해보자.
function foo() {
var a = 2;
this.bar();
}
function bar() {
console.log(this.a);
}
foo(); // Reference Error: a is no defined.
bar()
함수를this.bar()
로 참조하려는 것 부터가 문제foo()
와bar()
의 렉시컬 스코프 사이에 연결 통로를 만들어 변수 a 에 접근하게 하려는 시도지만 실패
→ 렉시컬 스코프 안에 있는 요소를 this 레퍼런스로 참조하기란 애당초 불가능하다.
1.3 this 는?
어떤 함수를 호출하면
활성화 레코드(Activation Record), 즉 실행 컨텍스트(Execution Context)가 만들어지고, 여기에 콜스텍과 호출방법, 전달된 인자 등의 정보가 담겨진다.
this 래퍼런스는 그 중 하나로 함수가 실행되는 동안 이용할 수 있다.
📌 this 정리
- this가 함수 자신이나 함수의 렉시컬 스코프를 가리키는 레퍼런스가 아니다.
- this는 작성 시점이 아닌 런타인 시점에 바인딩 된다
- this는 함수 호출 당시 상황에 따라 context가 결정된다.
- 즉, this 바인딩은 함수 선언 위치와 상관없이 어떻게 함수를 호출했느냐에 따라 달라진다.
This 2편 포스팅 에서 이어서 정리 예정
'프로그래밍 > JAVASCRIPT 사전' 카테고리의 다른 글
[JS] this란? 모든 케이스를 정리해보자 (0) | 2021.06.08 |
---|---|
[JS] 화살표 함수, 쉽고 빠르게 정리하기 (8) | 2021.05.11 |
[JS] arguments 객체 그리고 유사배열 객체 (0) | 2021.05.05 |
[JS] 문법정리 > 확실한 프로토타입 체이닝 정리 (0) | 2020.12.29 |
[JS] 문법 정리 > 함수: 선언, 호이스팅, 일급 객체 (0) | 2020.12.20 |
댓글
이 글 공유하기
다른 글
-
[JS] this란? 모든 케이스를 정리해보자
[JS] this란? 모든 케이스를 정리해보자
2021.06.08 -
[JS] 화살표 함수, 쉽고 빠르게 정리하기
[JS] 화살표 함수, 쉽고 빠르게 정리하기
2021.05.11 -
[JS] arguments 객체 그리고 유사배열 객체
[JS] arguments 객체 그리고 유사배열 객체
2021.05.05 -
[JS] 문법정리 > 확실한 프로토타입 체이닝 정리
[JS] 문법정리 > 확실한 프로토타입 체이닝 정리
2020.12.29