개발/Javascript

[You don't know JS] Part2 - 부록b. 스코프와 렉시컬 this

lanace 2020. 9. 6. 06:39

부록 B.1 동적 스코프


렉시컬 스코프는 엔진이 변수를 찾는 검색 방식과 위치에 대한 규칙이다.

개발자가 코드를 짤때 스코프가 결정된다. (eval, with 사용 없다는 가정 하에...)

동적 스코프는 런타임때 동적으로 결정하는 모델이다.

function foo() {
    console.log(a); // 2
}

function bar() {
    var a = 3;
    foo();
}

var a = 2;
bar();

javascript는 렉시컬스코프이기 때문에 foo에서 a는 RHS 참조를 했을때 렉시컬 스코프를 이용해 2를 가져온다.

동적 스코프는 콜스텍을 거슬러 올라가면서 찾기때문에 bar에 있는 3을참조한다.

차이점은 다음과 같다.

  • 렉시컬 스코프는 코드 작성시에,
    동적 스코프는 실행중 결정된다.
  • 렉시컬 스코프는 어디서 함수가 선언되었는지에 관련되어있지만
    동적 스코프는 어디서 함수가 호출되었는지에 관련이 있다.

부록 B.2 폴리필링 블록 스코프


이제 javascript도 블록스코프를 지원한다.

이전에도 switch문이나 with, catch를 통해 사용할 순 있었다.

ES5 환경에서 블록스코프는 아래와 같이 쓸 수 있다.

try {
    throw 2;
} catch(a) {
    console.log(a);
}

console.log(a);  // Refernce Error

부록 B.2.1 트레이서


구글에서 트레이서 라는 프로젝트를 진행중에 있다.

ES6 특성을 변형 컴파일 해서 ES6 이전 환경에서 이용하게 하는것이다.

얘도 catch를 활용할것이라고 상상하고 있다.

진짜 그런지는 알아보아야 한다.

부록 B.2.2 암시적 블록 vs 명시적 블록


결론적으로 지원하지 않는 문법을 설명하고, 이를 위해 다른 라이브러리를 사용해야 하기 때문에 단순 참조 정도로만 넘기는것을 추천한다.

let (a = 2) {
    console.log(a);  // 2
}

console.log(a);  // Reference Error

위의 구문처럼 let 구문으로 스코프를 명시하면 좋다.

코드가 더 깔끔하고, 선언의 위치를 강제로 위로 올려 찾기 쉽다.

공식적으로 지원하는 기능이 아니기 때문에 let-er 라는 라이브러리를 활용해야 한다.

컴파일 단계에서 아래와 같이 문법을 바꿔준다.

{
    let a = 2;
    console.log(a);
}

console.log(a); // Reference Error

부록 B.2.3 성능


IIFE로 스코프를 생성하지 않는 이유

  1. try/catch의 성능이 더 느리다.

    ⇒ 이건 무슨 상관이지?

  2. IIFE는 내부의 this, return, break, continue 같은 명령의 의미가 달라진다.

부록 B.3 렉시컬 this


Arrow function이 추가되었다.

var foo = (a) => {
    console.log(a);
}

foo(2);  // 2

this에 관련된 이슈

var obj = {
    id: 'awesome',
    cool: function coolFn() {
        console.log(this.id);
    }
};

var id = "not awesome";

obj.cool();  // 'awesome';
setTimeout(obj.cool, 100);  // 'not awesome';

cool 함수에 묶인 this가 사라진다.