Frontend/Study

[모던 자바스크립트 Deep Dive] 13장 ~ 15장

BeNI 2024. 11. 10. 18:16
728x90

13장 스코프 

 

1. 스코프란

: 식별자의 유효한 범위

 

식별자란, 변수나 함수의 이름 등을 의미한다.

식별자는 어떠한 값을 구별할 수 있어야 하므로 유일해야 한다. 즉 중복될 수 없다.

자바스크립트에서는 스코프라는 개념을 통해 식별자의 중복을 방지한다.

  • 렉시컬 환경 : 스코프를 구분하여 식별자를 등록/관리하는 저장소(상위 스코프에 대한 참조를 관리함)
  • 실행 컨텍스트 : 현재 실행중인 코드에 대한 데이터 구조를 담고있는 동적인 데이터 구조

스코프 내에서 식별자는 유일해야 하지만, 다른 스코프에서는 다른 이름의 식별자를 사용할 수 있다

즉, 스코프는 네임스페이스다 👍

 

2. 스코프의 종류

1) 전역 스코프

- 전역에서 선언된 변수는 전역 스코프를 가진다.

- 전역 변수는 어디서든지 참조할 수 있다.

 

2) 지역 스코프

- 함수 몸체 내부를 "지역" 이라고 한다.

- 지역에 변수를 선언하면 지역 스코프르 갖는 지역 변수가 된다.

- 지역 변수는 자신의 지역 스코프와 하위 지역 스코프에서 유효하다.

 

3. 스코프 체인

: 스코프가 함수의 중첩에 의해 계층적 구조를 갖는 것

  • 변수를 참조할 때 자바스크립트 엔진은 스코프 체인을 통해 변수를 참조하는 코드의 스코프에서 시작하여
    상위 스코프 방향으로 이동하며 선언된 변수를 검색함
  • 상위 스코프에서 유효한 변수는 하위 스코프에서 참조 가능
  • 하지만 하위 스코프에서 유효한 변수는 상위 스코프에서 참조할 수 없다.

 

4. 함수 레벨 스코프

- 지역 스코프는 코드 블록이 아닌 함수에 의해서만 생성된다.

- var로 선언된 변수는 오로지 함수 코드 블록만을 지역 스코프로 인정한다.

- let과 const는 블록 레벨 스코프를 지원한다.

 

ex) 일반 코드블록(if, for, while, try/catch)으로는 지역 스코프를 생성하지 못한다.

var x = 1;

if(true) {
  var x = 10;
}

console.log(x); // 10

 

 

5. 렉시컬 스코프

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

function bar() {
  console.log(x); // 함수를 선언한 위치에서 x는 1이다.
}

foo(); // 1
bar(); // 1
  • 동적 스코프 : 함수를 어디서 호출했는지에 따라 함수의 상위 스코프 결정
  • 렉시컬 스코프(정적 스코프) : 함수를 어디서 정의했는지에 따라 상위 스코프를 결정

자바스크립트는 렉시컬 스코프를 따른다 ! 

👉 함수를 어디서 호출했는지가 아닌 함수를 어디서 정의했는지에 따라 상위 스코프를 결정한다 !

 

 


14장 전역 변수의 문제점

 

1. 변수의 생명 주기

1) 지역 변수의 생명 주기

  • 지역변수의 생명 주기는 함수의 생명주기와 대부분 일치, 더 오래 사는 경우도 있다.
  • 변수의 생명 주기는 메모리 공간이 확보된 시점부터 메모리 공간이 해제되어 가용메모리 풀에 반환되는 시점까지
  • 누군가가 스코프를 참조하고 있으면 스코프는 소멸하지 않고 생존함
var x = 'global';

function foo() {
  console.log(x);
  var x = 'local';
}

foo();
console.log(x);

 

foo() 함수 내부에서 선언된 지역변수 x는 log를 찍을 때 함수 스코프 내에 선언되어있고 undefined로 초기화 되어있다.

따라서 foo()를 실행하면 undefined가 출력된다. (호이스팅)

 

✅ 호이스팅은 변수 선언이 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징을 말한다.

 

2) 전역 변수의 생명 주기

  • 코드가 로드되자마자 곧바로 해석되고 실행되며 더이상 실행할 문이 없을 때 종료한다.
  • var 키워드로 선언된 전역 변수는 전역 객체의 프로퍼티가 된다. 
  • 전역 변수의 생명주기는 전역 객체의 생명 주기와 일치한다.

* 전역 객체 : 코드가 실행되기 이전 단계에 자바스크립트 엔진에 의해 어떤 객체보다도 먼저 생성되는 특수한 객체

ex) 표준 빌트인 객체(Object, String, Number, ...), var로 선언한 전역 변수, 전역 함수 등 

 

2. 전역 변수의 문제점

  • 암묵적 결합 : 모든 코드가 전역 변수를 참조하고 변경할 수 있음
  • 긴 실행주기 
  • 스코프 체인 상에서 종점에 존재 : 전역 변수의 검색 속도가 제일 느리다
  • 네임 스페이스 오염 

변수의 스코프는 최대한 작을수록 좋다!

3. 전역 변수 사용을 억제하는 방법

1) 즉시 실행 함수(IIFE)

- 모든 코드를 즉시 실행 함수로 감싸면 모든 변수는 즉시 실행 함수의 지역 변수가 된다.

(function () {
  var foo = 1-;
  ...
}());

console.log(foo); // foo is not defined

 

2) 네임스페이스 객체

전역에 네임스페이스 객체를 생성하고 전역 변수처럼 사용하고 싶은 변수를 프로퍼티로 추가하는 방법

var MYAPP = {};

MYAPP.name = 'Lee';
console.log(MYAPP.name); // Lee

 

네임 스페이스를 분리해서 식별자 충돌을 방지하는 효과는 있으나, 네임 스페이스 객체 자체가 전역 변수에 할당되는 거라 유용하진 않음

 

3) 모듈 패턴

- 클래스를 모방해서 관련이 있는 변수나 함수를 모아 즉시 실행 함수로 감싸 하나의 모듈을 만드는 행위

var Counter = (function() {
  var num = 0;
  return {
    increase() {
      return ++num;
    },
    decrease() {
      return --num;
    }
  };
}());

console.log(Counter.num); // undefined;
console.log(Counter.increase()); // 1
console.log(Counter.increase()); // 2
console.log(Counter.decrease()); // 1
console.log(Counter.decrease()); // 0

마치 클래스에서 protected변수를 선언한 거와 같은 효과를 보여준다.

클로저의 개념..

 

4) ES6 모듈

- ES6 모듈은 파일 자체의 독자적인 모듈 스코프를 제공한다.

- script태그의 type="module" 어트리뷰트를 추가하면 로드된 자바스크립트 파일은 모듈로서 동작한다.

 

 

 


15장 let, const 키워드와 블록 레벨 스코프

 

1. var 키워드로 선언한 변수의 문제점

  • 중복 선언 가능
  • 함수의 코드 블록만을 지역 스코프로 인정
  • 변수가 호이스팅 됨 그래서 변수 선언문 이전에 참조하면 undefiend를 반환하게 됨

 

2. let 키워드 

  • 변수 중복 선언 금지
  • 블록 레벨 스코프 
  • 호이스팅이 발생하지 않는 것 처럼 동작

1) 변수 호이스팅

- var로 선언한 변수는 런타임 이전에 자바스크립트 엔진에 의해 암묵적으로 "선언 단계"와 "초기화 단계"가 한번에 진행된다.

- 선언 단계에서 스코프에 변수 식별자를 등록해 자바스크립트 엔진에 변수의 존재를 알리고 즉시 초기화 단계에서 undefiend로 초기화

 

- let으로 선언한 변수는 "선언 단계"와 "초기화 단계"가 분리되어 진행됨

- 선언 단계는 런타임 이전에 암묵적으로 실행되지만, 초기화 단계는 변수 선언문에 도달했을 때 실행된다.

🍎 TDZ(일시적 사각지대) : 스코프의 시작 지점부터 초기화 시작 지점까지 변수를 참조할 수 없는 공간

 

2) 전역 객체와 let

var 키워드로 선언한 전역 변수와 전역 함수, 그리고 암묵적 전역은 전역 객체 window의 프로퍼티가 된다.

하지만 let 키워드로 선언한 전역 변수는 전역 객체의 프로퍼티가 아님. window로 접근 불가 !!

 

✅ let 전역 변수는 보이지 않는 개념적인 블록(전역 렉시컬 환경의 선언적 환경 레코드) 내에 존재

 

3. const 키워드

- const 키워드로 선언한 변수는 반드시 선언과 동시에 초기화 해야함

- 재할당 금지 :  const 키워드로 선언된 변수에 원시 값을 할당한 경우 원시 값은 변경할 수 없는 값

- const 키워드로 선언된 변수에 객체를 할당한 경우 값을 변경할 수 없다.

 

 

 

 

 

 

 

 

오랜만의 포스팅..

728x90