[Javascript Deepdive] 변수 선언 및 호이스팅

Gyuhan Park·2022년 11월 4일
0

javascript deepdive

목록 보기
1/11

var 키워드로 선언한 변수는 변수 중복 선언, 함수 레벨 스코프, 변수 호이스팅으로 인해 의도치 않은 오류가 발생할 수 있다. 이를 개선한 ES6의 let, const는 블록 레벨 스코프를 지역 스코프로 인정하며 TDZ로 변수 호이스팅으로 인한 오류를 줄인다.

📘 변수

하나의 값을 저장하기 위해 확보한 메모리 공간 자체
또는 그 메모리 공간을 식별하기 위해 붙인 이름 -> 식별자
식별자는 값이 아니라 메모리 주소 기억
변수는 저장된 메모리 주소를 이용해 값에 접근 가능

var 키워드로 변수 선언 시 확보된 메모리 공간에는 JS 엔진에 의해 undefined라는 값이 암묵적으로 할당되어 초기화

✅ JS엔진은 2단계에 거쳐 변수를 선언한다

  • 선언 단계 : 변수 이름을 등록해서 JS 엔진에 변수의 존재를 알린다.
  • 초기화 단계 : 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화한다.

✅ 변수 이름은 어디에 등록되는가?

  • 변수 이름을 비롯한 모든 식별자는 실행 컨텍스트 에 등록
  • 변수 이름과 변수 값은 실행 컨텍스트 내에 key/value 형식인 객체로 등록되어 관리

var 키워드를 사용한 변수 선언은 선언 단계와 초기화 단계가 동시에 진행
선언되지 않은 식별자에 접근하여 JS엔진이 등록된 식별자를 찾을 수 없을 때 ReferenceError 발생

📘 값의 할당

변수 선언과 값의 할당의 실행 시점이 다름

  • 변수 선언은 런타임 이전에 실행
  • 값의 할당은 런타임에 실행

undefined가 저장된 메모리 공간 외에 새로운 메모리 공간을 확보하여 80 저장

console.log(score); // undefined
var score = 80;
console.log(score); // 80

어떤 식별자도 참조하지 않는 메모리 공간은 가비지 콜렉터에 의해 메모리에서 자동 해제 (언제 될 지는 모름)

✅ var 의 문제점

  • 변수 중복 선언 허용
  • 함수 레벨 스코프
  • 변수 호이스팅

변수 중복 선언 허용
변수를 중복 선언하여 재할당한다면, 의도치 않게 먼저 선언된 변수 값이 변경될 수 있음

함수 레벨 스코프
var 키워드로 선언한 변수는 모두 함수 레벨 스코프
의도치 않게 전역 변수를 중복 선언하는 경우 발생

변수 호이스팅
변수 호이스팅에 의해 변수 선언문 이전에 참조 가능
할당문 이전에 변수를 참조하면 언제나 undefined 발생
에러를 발생시키진 않지만 가독성 저하, 의도치 않은 오류 발생 위험성 존재

✅ let

ES6에 도입된 let과 const는 var의 문제점을 해결

  • 변수 중복 선언 금지
  • 블록 레벨 스코프
  • 변수 호이스팅
  • 전역 객체와 let

변수 중복 선언 금지
같은 변수를 중복 선언하면 SyntaxError 발생

블록 레벨 스코프
모든 코드 블록(함수, if, for, while, try/catch 등)을 지역 스코프로 인정하는 블록 레벨 스코프

전역 객체와 let
var 키워드로 선언한 전역 변수, 전역 함수, 선언하지 않은 변수에 값을 할당한 암묵적 전역
→ 전역 객체 window의 프로퍼티
let 키워드로 선언한 전역 변수는 전역 객체의 프로퍼티 ❌
→ window가 아닌 전역 렉시컬 환경의 선언적 환경 레코드 내에 존재

✅ const

상수를 선언하기 위해 사용하지만, 상수만을 위해 사용 ❌

  • 선언과 초기화
  • 재할당 금지
  • 상수
  • const 키워드와 객체

선언과 초기화
반드시 선언과 동시에 초기화해야 한다
블록 레벨 스코프를 가지며, 변수 호이스팅이 발생하지 않는 것처럼 동작

상수
상태 유지, 가독성, 유지보수 의 편의를 위해 적극적으로 사용해야 한다
상수를 사용하면 값의 의미를 쉽게 파악 할 수 있고, 프로그램 전체에서 고정값으로 사용 할 수 있음
일반적으로 상수의 이름은 대문자 로 선언하며, 스네이크 케이스 로 표현

// ❌
let preTaxPrice = 100;
let afterTaxPrice = preTaxPrice + (preTaxPrice * 0.1);

// ✅
const TAX_RATE = 0.1;
let preTaxPrice = 100;
let afterTaxPrice = preTaxPrice + (preTaxPrice * TAX_RATE);

const 키워드와 객체
const 키워드로 선언된 변수에 객체를 할당한 경우 값 변경 가능
재할당을 금지할 뿐 불변 의미 ❌

📘 변수 호이스팅

변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 것

  1. 변수 선언을 포함한 모든 선언문 먼저 실행 (소스코드의 평가과정)
  2. 소스코드를 한 줄씩 순차적으로 실행 (런타임)

✅ var 변수 호이스팅

변수 호이스팅에 의해 선언 단계와 초기화 단계가 동시에 진행되어 result가 런타임 이전에 선언되고 undefined로 초기화
값의 할당은 런타임에 실행되기 때문에 선언문에 도달했을 때 30으로 재할당

console.log(result); // 1. undefined
var result = 30;
console.log(result); // 2. 30

✅ let, const 변수 호이스팅

변수 선언문 이전에 참조하면 ReferenceError 발생
let 키워드로 선언한 변수는 선언 단계와 초기화 단계가 분리 되어 진행
런타임 이전에 JS엔진에 의해 선언 단계 먼저 실행
초기화 단계는 변수 선언문에 도달했을 때 실행

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

변수 호이스팅이 발생하지 않는 것처럼 보이지만 다음 코드를 실행해보면 발생한다는 것을 알 수 있음
호이스팅이 일어나지 않는다면 전역변수 foo의 1이 출력되겠지만 Reference Error가 발생

let foo = 1;
{
	console.log(foo); // Reference Error
	let foo = 2;
}

자바스크립트는 모든 선언을 호이스팅하지만 let, const, class 선언문은 안하는 것처럼 동작한다

📘 var, let, const 비교

기본적으로 const를 사용하고 let은 재할당이 필요한 경우에만 사용 하는 것이 좋음

  • ES6에서는 var 키워드 사용 ❌
  • 재할당이 필요할 때만 let 키워드 사용하고, 스코프를 최대한 좁게 유지
  • 재할당이 필요없는 상수와 객체에는 const 사용
profile
단단한 프론트엔드 개발자가 되고 싶은

0개의 댓글