무분별한 전역변수 사용 지양해야 함
(1) 변수의 생명 주기
- 선언에 의해 생성 → 할당을 통해 값 가짐 → 소멸
- 자신이 선언된 위치에서 생성되고 소멸함
전역 변수
의 생명 주기= 애플리케이션의 생명 주기
- 함수 내부에서 선언된
지역변수
= 함수 호출시 생성 → 함수 종료시 소멸 - = 함수의 생명주기와 같음
💡
전역 변수
변수 선언은 선언문이 어디에 있든 상관없이 가장 먼저 실행됨
변수 선언은 런타임 이전 단계에서 자바스크립트 엔진에 의해 먼저 실행됨
함수 내부에서 선언한 변수
함수가 호출된 직후에 함수 몸체의 코드가 한 줄씩 순차적으로 실행되기 이전에 자바스크립트 엔진에 의해 먼저 실행됨 (변수 먼저 선언되어 undefined로 초기화된 후 함수 몸체를 구성하는 문들이 순차적으로 실행되기 시작할 때 변수 할당문이 실행되면 x 변수에 값이 할당됨)
함수가 종료되면 함수 내부에서 선언된 지역 변수도 소멸되어 생명 주기가 종료됨
함수 내부에서 선언된 지역 변수는 함수가 호출되어 실행되는 동안에만 유효함
변수 선언은 선언문이 어디에 있든 상관없이 가장 먼저 실행됨
변수 선언은 런타임 이전 단계에서 자바스크립트 엔진에 의해 먼저 실행됨
함수 내부에서 선언한 변수
함수가 호출된 직후에 함수 몸체의 코드가 한 줄씩 순차적으로 실행되기 이전에 자바스크립트 엔진에 의해 먼저 실행됨 (변수 먼저 선언되어 undefined로 초기화된 후 함수 몸체를 구성하는 문들이 순차적으로 실행되기 시작할 때 변수 할당문이 실행되면 x 변수에 값이 할당됨)
함수가 종료되면 함수 내부에서 선언된 지역 변수도 소멸되어 생명 주기가 종료됨
함수 내부에서 선언된 지역 변수는 함수가 호출되어 실행되는 동안에만 유효함
❗지역 변수가 함수보다 오래 생존하는 경우
변수
: 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메로리 공간을 식별하기 위해 붙인 이름- 생명주기: 메모리 공간이 확보된 시점 ~ 메모리 공간이 해제되어 가용 메모리 풀에 반환되는 시점
- 함수 내부에서 선언된 변수 = 함수가 생성한 스코프에 등록
- 함수가 생성한 스코프 = 물리적인 실체 존재 (렉시컬 환경)
- 변수: 자신이 등록된 스코프가 소멸(메모리 해제)될 때까지 유효
- 할당된 메모리 공간 더이상 참조 X → 가비지 콜렉터에 의해 해제되어 가용 메모리 풀에 반환됨
- 누군가가 메모리 공간 참조 → 해제되지 않고 확보된 상태로 남아있게 됨
- 스코프도 변수와 마찬가지 ⇒ 누군가가 스코프 참조시 소멸하지 않고 생존
- 일반적으로 함수가 종료하면 함수가 생성한 스코프도 소멸
- 누군가가 스코프 참조시 해제되지 않고 생존
var x = 'global';
function foo() {
console.log(x);
var x = 'local';
}
foo(); // undefined
console.log(x); // global
- foo 내부에서 선언된 x는 foo 호출 직후에 선언되며 undefined로 초기화됨
- 변수 할당문이 실행되기 이전까지 undefined 값 가짐
호이스팅
: 변수 선언이 스코프의 선두로 끌어 올려진 것처럼 동작하는 자바스크립 고유의 특징- 스코프 단위로 동작함
- 전역 변수의 호이스팅: 전역 변수의 선언이 전역 스코프의 선두로 끌어 올려진 것처럼 동작
- 지역 변수의 호이스팅: 지역 변수의 선언이 지역 스코프의 선두로 끌어 올려진 것처럼 동작
- 지역 변수는 함수 전체에서 유효함
전역 변수의 생명 주기
- 전역 코드
- 명시적인 호출 없이 실행됨
- 함수 호출과 같이 전역 코드를 실행하는 특별한 진입점이 없음
- 로드되자마자 곧바로 해석 후 실행
- 마지막 문이 실행되어 더 이상 실행할 문이 없을 때 종료
- 함수
- 함수 몸체의 마지막 문 또는 반환문이 실행되면 종료
전역 객체
코드가 실행되기 이전에 자바스크립트 엔진에 의해 어떤 객체보다도 먼저 생성되는 특수한 객체
- 환경에 따른 객체
- 클라이언트 사이드 환경(브라우저) =
window
- 서버 사이드 환경(Node.js) =
global
- 환경에 따라 전역 개체 가리키는 다양한 식별자 존재
window.self
,this, frames
,global
- ES11에서
globalThis
로 통일
- 클라이언트 사이드 환경(브라우저) =
- 전역 객체가 갖는 프로퍼티
- 표준 빌트인 객체
- Object, String, Number, Function, Array
- 환경에 따른 호스트 객체
- 클라이언트 Web API, Node.js의 호스트 API
- var 키워드로 선언한 전역 변수와 전역 함수
- 표준 빌트인 객체
- var 키워드로 선언된 변수 =
전역 객체
의 프로퍼티가 됨⇒ 전역 변수의 생명 주기 = 전역 객체의 생명 주기- 브라우저 환경에서 var 키워드로 선언한 전역 변수 = 전역 객체 window의 프로퍼티
- 전역 객체 window : 웹페이지 닫기 전까지 유효
- var 키워드로 선언된 변수도 마찬가지
- 전역 객체 window : 웹페이지 닫기 전까지 유효
- 브라우저 환경에서 var 키워드로 선언한 전역 변수 = 전역 객체 window의 프로퍼티
(2) 전역 변수의 문제점
- 전역변수 선언 의도 = 암묵적 결합 허용
암묵적 결합
- 모든 코드가 전역 변수를 참조하고 변경할 수 있는 것
- 코드 어디서든 참조하고 할당할 수 있는 변수 선언하는 것
- 변수의 유효 범위 ↑ ⇒ 코드 가독성 ↓ & 의도치 않은 상태 변경 위험성 ↑
- 전역 변수의 긴 생명 주기 → 오랜 메모리 리소스 소비 기간 → 전역 변수 상태 변경 가능성 ↑
- 전역변수는 스코프 체인 상에서 종점에 존재⇒ 변수 검색 시 가장 마지막에 검색 되므로 검색 속도 가장 느림
- 네임 스페이스 오염
- JS의 가장 큰 문제점
- 하나의 파일이 분리되었다고 해도 하나의 전역 스코프를 공유한다는 점
- 다른 파일 내에서 동일한 이름으로 명명된 전역 변수·함수 같은 스코프에 존재할 가능성 有 ⇒ 예상치 못한 결과 초래
- 하나의 파일이 분리되었다고 해도 하나의 전역 스코프를 공유한다는 점
- JS의 가장 큰 문제점
(3) 전역 변수의 사용을 억제하는 방법
- 전역 변수 사용할 이유 없다면 지역 변수 사용해야 함
- 변수의 스코프는 좁을수록 좋음
방법1 ) 즉시 실행 함수
- 즉시 실행 함수: 함수 정의와 동시에 단 한번만 호출
- 모든 코드 즉시 실행 함수로 감쌀 시 모든 변수는 즉시 실행 함수의 지역 변수가 됨
방법2 ) 네임 스페이스 객체
- 전역에 네임 스페이스를 담당할 객체 생성 후 전역 변수처럼 사용하고 싶은 변수를 프로퍼티로 추가하는 방법
- 네임 스페이스 객체에 또 다른 네임 스페이스 객체를 프로퍼티로 추가하여 네임스페이스 계층적 구성 가능
- 네임 스페이스 분리하여 식별자 충돌을 방지 가능
- 네임 스페이스 객체 자체가 전역 변수이므로 크게 유용 x
var MYAPP = {};
MYAPP.name = 'Lee';
MYAPP.person = {
name: 'Lee',
address: 'Seoul',
}
방법3 ) 모듈 패턴
- 클래스를 모방해서 관련 있는 변수와 함수를 모아 즉시 실행 함수로 감싸 하나의 모듈 생성
- 클로저를 기반으로 동작
- 자바스크립트의 가장 강력한 기능
- 캡슐화 구현 가능
프로퍼티
와메서드
를 하나로 묶는 것- 프로퍼티: 객체의 상태를 나타냄
- 메서드: 프로퍼티를 참조하고 조작할 수 있는 동작
- 객체의 특정 프로퍼티나 메서드를 감출 목적으로도 사용 ⇒
정보 은닉
- 전역 네임스페이스의 오염 방지와 정보 은닉 구현 목적으로 사용
var Counter = ( function() { var num = 0; // 외부로 공개할 데이터나 메서드를 프로퍼티로 추가한 객체 반환 return { increase(){ return num++; }, decrease(){ return num--; } } } ()); // private 변수는 외부로 노출되지 않음 console.log(Counter.num); // undefined console.log(Counter.increase()); // 1 console.log(Counter.decrease()); // 0
- 위 예제의 즉시 실행 함수: 객체 반환
- 외부에 노출하고 싶은 변수나 함수를 담아 반환
퍼블릭 멤버
: 반환되는 객체의 프로퍼티 (외부에 노출됨)
프라이빗 멤버
: 외부로 노출하고 싶지 않은 변수나 함수- 반환하는 객체에 추가하지 않으면 됨
- 외부에 노출하고 싶은 변수나 함수를 담아 반환
- 위 예제의 즉시 실행 함수: 객체 반환
방법4 ) ES6 모듈
- ES6 모듈 사용시 전역 변수 사용 불가능
- 파일 자체의 독자적인 모듈 스코프 제공
- 모듈 내에서 var 키워드로 선언한 변수≠ 전역변수
- ≠ window 객체의 프로퍼티
- 모던 브라우저에서 사용 가능
- script 태그에 type=”module” 어트리뷰트 추가시 로드된 자바스크립트 파일 = 모듈로서 동작
- 모듈 확장자 =
mjs
- 모듈 확장자 =
- 브라우저의 ES6 모듈 기능 사용시 트랜스파일링, 번들링 필요⇒
일반적인 사용
브라우저 지원 ES6 모듈 기능 < 모듈 번들러 (ex. Webpack)