As i wish

[You don't know JS] - this라나 뭐라나 본문

JavaScript

[You don't know JS] - this라나 뭐라나

어면태 2019. 5. 8. 23:34

기본은 모르고 자꾸 개발만 하다 보니

이상하게 제 지식이 역삼각형 형태가 되는 것 같아서.

기본적인 책을 사서 읽어보고 정리를 하려고 합니다.

책은 한빛미디어에서 나온 "You don't know JS - 카일 심슨"의 책을 바탕으로 정리해보겠습니다!

 

우선 this는 모든 함수 스코프 내에 자동으로 설정되는 특수한 식별자입니다.

일단 스코프란 링크를 참조해 주세요.

 

일단 this 가 사용된 코드를 보겠습니다.

function identify() {
    return this.name.toUpperCase();
}

function speak() {
    var greeting = 'Hello, Im ' + identify.call(this);
}

var me = {
    name: 'Kyle'
};

var you = {
    name: 'Reader'
};

identify.call(me); // KYLE
identify.call(you); // READER

speak.call(me); // Hello, Im KYLE
speak.call(you); // Hello, Im READER

똑같은 코드를 this를 쓰지 않고 작성할 수도 있죠.

function identify(context) {
    return context.name.toUpperCase();
}

function speak(context) {
    var greeting = 'Hello, Im ' + identify(context);
}

var me = {
    name: 'Kyle'
};

var you = {
    name: 'Reader'
};

identify(me); // KYLE
identify(you); // READER

speak(me); // Hello, Im KYLE
speak(you); // Hello, Im READER

책에서는 사용 패턴이 복잡해질수록 두 번째처럼 context를 넘기는 방법이 this를 사용하는 것보다 코드가 더 지저분해진다고 설명하고 있습니다.

 

일단 this가 헷갈리는 방법은 2가지 정도가 있는데 1. 자기 자신, 2. 자신의 스코프라고 명시하고 있어요. 하나 둘 다 틀렸습니다!

그럼 하나씩 정리해 보도록 하겠습니다.

1. 자기 자신

function foo(num) {
    console.log('foo' + num);
    this.count++;
}

foo.count = 0;

var i;
for (i=0; i<10; i++) {
    if (i>5) {
        foo(i);
    }
}

//foo: 6
//foo: 7
//foo: 8
//foo: 9

console.log(foo.count) // 0 --?

위처럼 this가 자기 자신이라 하면 마지막에 foo.count를 찍었을 때에 '0' 이 아니어야 합니다.

그렇기 때문에 this가 자기 자신이라고 생각하는 것은 잘못된 생각입니다.

 

2. 자신의 스코프

this 가 바로 함수의 스코프를 가리킨다는 말은 흔한 오해입니다. 어떤 면에서는 맞지만 잘못 이해한 것이긴 한데 살짝 까다롭습니다.

분명한 건 this는 어떤 식으로도 함수의 렉시컬 스코프를 참조하지 않습니다. 내부적으로 스코프는 별개의 식별자가 달린 프로퍼티로 구성된 객체의 일종이나, 스코프 '객체'는 자바스크립트 구현체인 '엔진'의 내부 부품이기 때문에 일반 자바스크립트 코드로는 접근하지 못합니다.

이번 코드에서는 this가 암시적으로 함수의 렉시컬 스코프를 가리키도록 해보겠습니다.

렉시컬 스코프에 대한 글은 여기 링크를 참조해 주세요.

조금 더 쉽게 설명한 글도 있어요. 링크

function foo() {
    var a = 2;
    this.bar();
}

function bar() {
    console.log(this.a);
}

foo() // a is not defined

이렇게 this는 참조되지 않습니다.

이 코드는 foo()와 bar()의 렉시컬 스코프 사이에 어떤 연결 통로를 만들어 bar()가 foo()의 내부 스코프에 있는 변수 a에 접근하고 싶었겠지만 애당초 그런 거는 없습니다!

즉, 책에서는 this와 렉시컬 스코프 참조가 계속 헷갈리시면 이 말을 되니 길 바란데요. '연결 통로 따윈 없어!'

정리

- this는 작성 시점이 나닌 런타임 시점에 바인딩되며 함수 호출 당시 상황에 따라 context가 결정됩니다. 함수 선언 위치와 상관없이 this 바인딩은 오로지 어떻게 함수를 호출했냐가 중요하네요.

- this는 실제로 함수 호출 시점에 바인딩 되며 무엇을 가리킬지는 전적으로 함수를 호출한 코드에 달렸습니다!

 

1장은 이렇게 정리가 되겠네요.

궁금하거나 이해가 안 되는 부분은 댓글로 적어 주시면 감사하겠습니다.

 

* 참고자료

자바스크립트의 스코프와 클로저

스코프   

함수의 범위(scope)    

javascript - scope, lexical, hoisting   

[javascript] 유효 범위(scope)와 let, const  

Comments