[230228 - TIL] [모던 자바스크립트 Deep Dive] ~15장 - (2)

Dongwoo Kim·2023년 2월 28일
0

TIL / WIL

목록 보기
88/113

1. 개요

어제에 이어서 모던자바스크립트 내용을 정리해보자.

[230227 - TIL] [모던 자바스크립트 Deep Dive] ~15장 - (1)


2. 스코프

스코프는 식별자의 유효범위를 뜻한다.
식별자는 스코프에 해당하는 유효범위에서만 다른 코드가 자신을 참조할 수 있게 된다.

스코프에 따라 같은 이름의 식별자도 다른 변수일 수 있다.

이름이 같은 두개의 변수가 있다면 어떤 변수를 참조할 것인지 식별자 결정을 하게된다. 이때 렉시컬 환경에 따라 해당 스코프의 상태에 따라 결정하게 된다

렉시컬 환경

"코드가 어디서 실행되며 주변에 어떤 코드가 있는지"를 뜻한다.
코드의 문맥은 렉시컬 환경으로 이뤄지며 이를 구현한 것이 실행 컨텍스트다. 모든 코드는 실행 컨텍스트에서 평가되고 실행된다. 모든 식별자는 실행 컨텍스트에 등록된다.

실행 컨텍스트

자바스크립트 엔진이 소스코드를 평가하고 실행하기 위해 필요한 환경을 제공하고 코드의 실행결과를 실제로 관리하는 영역이다. 자바스크립트 엔진은 실행 컨텍스트를 통해 식별자와 스코프를 관리한다.

스코프 체인

함수가 중첩되어 계층적 구조를 가지듯이 스코프도 계층적 구조를 가질 수 있고 이를 계층적 연결 구조로 나타낸 것이 스코프 체인이다.

변수를 참조할 때는 스코프 체인을 통해 변수를 참조하는 코드의 스코프부터 상위 스코프로 이동하며 선언된 변수를 찾는다.

함수레벨 스코프 vs 블록레벨 스코프

var 변수는 함수의 코드블록을 지역 스코프로 인정한다.
let과 const 변수는 블록레벨 (if, for 등)을 지역 스코프로 인정한다.

따라서 블록레벨에서 선언된 var 변수는 전역변수가 되고 혼란을 야기할 수 있다.

렉시컬 스코프

변수가 아닌 함수는 어떻게 스코프를 결정할까?
1. 함수를 어디서 호출했는지에 따라 -> 동적 스코프
2. 함수를 어디서 정의했는지에 따라 -> 정적 스코프

자바스크립트는 렉시컬 스코프, 즉 정적 스코프를 따라 상위 스코프를 결정한다.

var x = 1;

function foo() {
  var x = 10;
  bar();
}

function bar() {
  console.log(x);
}

foo();	// 1
bar();	// 1

3. 생명주기

라이프사이클

변수에는 선언으로 생성되고 할당을 통해 값을 가진다. 그리고 변수가 생성되고 소멸될 때까지를 생명주기라고 한다. 변수에 생명 주기가 없다면 메모리 공간을 계속 차지하게 된다.

전역변수 vs 지역변수

전역변수는 실행한 애플리케이션의 생명주기와 같다.
지역변수는 해당 스코프의 생명주기와 일치한다. 다만 아닌 경우도 있다. 생명주기는 메모리 공간에 확보되고 다시 해제되어 가용메모리 풀에 반환되는 시점까지다. 따라서 외부에서 해당 지역변수, 또는 스코프를 참조하고 있으면 해당 지역변수, 스코프는 해제되지않는다.

호이스팅은 스코프 단위로 동작한다.

var x = "global";

function foo() {
	console.log(x); // undefined
  	var x = "local";
}

foo();
console.log(x);	// global

해당 코드에서는 foo() 함수 스코프에서 호이스팅이 일어나 x가 전역변수가 아닌 지역변수로 선언되고 값을 할당받기 전까지 undefined 값을 가진다. 따라서 foo()함수의 console.log(x)는 undefined을 출력한다.

전역변수의 문제점

  1. 어디서는 참조하고 할당할 수 있기 때문에 가독성이 나빠지고 의도치않은 결과를 얻을 수 있다.
  2. 긴 생명주기 -> 메모리 차지 ↑
  3. 스코프 체인 상에서 종점에 존재하기 때문에 검색 속도가 가장 느리다.
  4. 네임스페이스 오염

    자바스크립트의 가장 큰 문제점 중 하나는 파일이 분리되어 있다 해도 하나의 전역 스코프를 공유한다는 것

    따라서 다른 파일에 동일한 이름의 전역 변수가 존재하면 오류가 생길 수 있다.

4. let, const

var vs let

  1. 중복 선언 허용 : var 가능 / let 불가능

    	var bar = 123;
    	var bar = 1234; // 중복 선언 허용
    
    	let foo = 123;
    	let foo = 1234; // SyntaxError
  1. 스코프 : var 함수레벨 스코프 / let 블록레벨 스코프

    	var bar = 123;
    	let foo = 123;
    
        {
            var bar = 1234
            let foo = 1234;
        }
    
        console.log(bar) // 1234
        console.log(foo) // 123
  1. 변수 호이스팅 : var 가능 / let 안되는 것처럼 동작

    	console.log(bar) // 123
    	console.log(foo) // ReferenceError
    
        var bar = 123;
    	let foo = 123;
    	 let foo = 123;
         {
         	console.log(foo); // ReferenceError
            let foo = 1234;
         }

const

const 변수는 선언과 동시에 반드시 초기화해야하고 값은 변경할 수 없다.

const foo; // SyntaxError

const foo = 123;
foo = 1234; // TypeError

const 변수는 let 변수와 마찬가지로 변수호이스팅이 발생하지 않는 것처럼 동작하며 블록레벨 스코프를 가진다.

const 객체

const변수로 원시값을 할당하면 값을 변경할 수 없지만 객체를 할당한 경우 값을 변경할 수 있다.

const obj = {
	foo: 123
};

obj.foo = 1234;

console.log(obj); // {foo: 1234}


책 정보

2020, 이웅모, 모던 자바스크립트 Deep dive

profile
kimphysicsman

0개의 댓글