fffo

전역변수의 문제점 / let, const 키워드와 블록 스코프 본문

Programming/Javascript

전역변수의 문제점 / let, const 키워드와 블록 스코프

gggs 2021. 9. 29. 15:30

전역 변수의 문제점

변수의 생명 주기

  • 변수가 런타임 이전에 선언되는 것은 전역변수 한정
  • 지역 변수는 해당 스코프가 실행 될 때 선언되고 스코프가 끝날 때 소멸 됨
  • 변수가 할당된 메모리 공간은 누군가가 참조하고 있지 않을 때 가비지 콜랙터에 의해 해제 됨 → 누군가 참조하고 있다면 해제되지 않고 남아있음
  • 일반적으로 함수가 종료되면 함수가 생성한 스코프도 소멸하지만 누군가 스코프를 참조하고 있으면 스코프는 해제되지 않고 생존 → 클로저

전역 객체

  • 전역 객체 : 코드가 실행되기 이전 단계에 js엔진에 의해 어떤 객체보다도 먼저 생성되는 특수한 객체
    • 브라우저 : window
    • node.js : global
    • 환경에 따라 전역 객체를 가리키는 다양한 식별자(window, self, this, frames, global)가 존재했으나 ES11에서 globalThis로 통일됨
  • 전역 객체는 표준 빌트인 객체, 환경에 따른 호스트 객체, var키워드로 선언한 전역변수와 전역 함수를 프로퍼티로 가짐
    • 표준 빌트인 객체 : Object, String, Function, Array 등
    • 환경에 따른 호스트 객체 : 클라이언트의 Web API, Node.js의 호스트 API

전역 변수의 문제점

  • 암묵적 결합 : 모든 코드가 전역 변수를 참조하고 변경할 수 있음
  • 긴 생명 주기 : 메모리 리소스를 오래 소비, 의도치 않은 재할당 초래
  • 스코프 체인 상에서 종점에 존재 : 변수 검색 시 전역 변수의 검색 속도가 가장 느림
  • 네임스페이스 오염 : 파일이 분리되어 있어도 전역 스코프를 공유함

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

  • 지역변수 이용 지향, 스코프는 최대한 좁게 사용
  • 즉시 실행 함수 : 모든 코드를 즉시 실행 함수로 감싸면 모든 변수가 즉시 실행 함수의 지역 변수가 됨 → 라이브러리 등에 자주 사용됨
  • 네임스페이스 객체 : 전역에 네임스페이스 역할을 할 객체 생성 후 전역 변수처럼 사용할 변수를 프로퍼티로 추가.
    • 네임스페이스 내에 또 다른 네임스페이스 객체를 계층적으로 구성 가능
    • 식별자 충돌을 방지할 수 있으나 네임스페이스 객체 자체가 전역 변수에 할당되므로 그리 유용한 방식은 아님
  • 모듈 패턴 :
var Counter = (function() {
    // private 변수
    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
  • ES6 모듈 : 파일 자체의 독자적인 모듈 스코프 제공, 전역 변수 사용 불가. 구형 브라우저에서는 동작하지 않음

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

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

  • 변수 중복 선언 허용
    • 중복 선언 시 초기화문이 있으면 js엔진에 의해 var 키워드가 없는 것처럼 동작, 초기화문이 없으면 무시됨
  • 함수 레벨 스코프
    • 오직 함수의 코드 블록만 스코프만 지역 스코프로 인정
    • if문 for문 등 다른 코드 블록은 모두 전역 스코프
  • 변수 호이스팅으로 인한 가독성 저하 및 오류 발생 유발

let 키워드

  • ES6에서 새로 나온 변수 선언 키워드
  • 변수 중복 선언 금지
  • 블록 레벨 스코프 적용

let 키워드 변수의 호이스팅

  • 변수 호이스팅이 발생하지 않는 것 처럼 동작
    • 선언 단계와 초기화 단계가 분리되어 진행
    • 런타임 이전에 선언단계가 실행 되지만 undefined로의 초기화는 변수 선언문에 도달 했을 때 실행 됨
    • 일시적 사각지대(Temporal Dead Zone; TDZ) : 스코프 시작 ~ 초기화 시작
    • 모든 선언은 호이스팅됨. 그러나 let, const, class는 호이스팅이 발생하지 않는 것처럼 동작함

전역 객체와 let

  • var 키워드로 선언한 전역 변수, 전역 함수, 암묵적 전역은 전역객체의 프로퍼티가 됨
  • 그러나 let으로 선언한 전역 변수는 전역객체의 프로퍼티가 아닌 개념적인 블록 내에 존재
// 브라우저 환경에서 실행
var x = 1;
y = 2; // 암묵적 전역
let z = 3;

console.log(window.x); // 1
console.log(window.y); // 2
console.log(window.z); // undefined

const 키워드

  • 주로 상수 선언 시 사용
  • let 키워드와 대부분 동일하지만 몇 가지 차이점 존재
    • 반드시 선언과 동시에 초기화 해야 함
    • 재할당 금지
  • 상수의 이름은 대문자로 선언 권장, 스네이크 케이스로 표현 일반적
  • const 키워드로 선언된 객체는 재할당이 불가능 할 뿐, 변경 가능함
  • 기본적으로 const를 사용하고 재할당이 필요한 변수일 경우만 let을 사용 권장

'Programming > Javascript' 카테고리의 다른 글

생성자 함수에 의한 객체 생성  (0) 2021.10.01
프로퍼티 어트리뷰트  (0) 2021.09.30
스코프  (0) 2021.09.28
js 복습 - 깊은복사, 생성자, Date  (0) 2021.09.27
함수  (0) 2021.09.27
Comments