본문 바로가기

1.웹개발/JS

var와 let/const의 차이

핵심은 "var의 단점을 알고 있는가?"라고 생각합니다.

 

나아가, 호이스팅에서의 차이를 알고 있느냐를 묻는다고 생각합니다.

var, let , const는 '변수'를 선언하기 위한 키워드입니다

변수에 대한 필요성 등은 프로그래밍 공부 시 처음 배우는 내용입니다.(중요)

var키워드의 단점은


1. 암묵적 결합(중복 선언 가능)
2. 생략 가능
3. 변수 호이스팅

4. 함수 레벨 스코프

등 단점들이 있습니다.

let은 이러한 단점을 해결해서
es6에서 출시된 키워드라고 이해하면 됩니다.

하나씩 보겠습니다.

 

1. 암묵적 결합(중복 선언 가능)

(function() {
  var variable = 'hi i am var keyword';
  var variable = 'Redundancy declaration';
  
  console.log(variable);
})();

 

위와 같은 함수가 있습니다. 앞으로의 예제는 즉시 실행 함수이기 때문에 호출하지 않아도 자동으로 실행됩니다.

variable이라는 변수에 할당된 값은 console에 어떻게 출력될까요?

 

정답은 Redundancy declaration입니다.
같은 이름의 변수를 중복을 허용한 예시입니다

 

무슨 문제가 되냐고 묻는다면, 코드가 길어졌을 때, 자주 사용하는 변수명에 값이 예상과는 다를 수 있습니다.

그럴 일 없게 작성해야 되는 것 아니냐고요?


물론 그럴 일 없게 변수명을 작성하는 게 중요하지만, 사람은 실수를 할 수 있기 때문에 실수를 방어하는 역할이 필요합니다. 또한 코드가 길어지면 충분히 중복되는 변수가 생길 수도 있으며, 혼자 프로그래밍하지 않고 협업을 한다면 코드를 하나하나 분석하지 않고 다른 사람이 수정하게 된다면 예상이 불가능할 수 있습니다.

 

(function() {
  variable = 'no var';
  
  console.log(variable);
})();

console.log(variable);

키워드 없이 변수에 값을 할당하였습니다. 위에 선언문이 있는 경우엔 재할당이지만,
선언문이 없는 경우 var 키워드로 선언한 것처럼 전역에 메모리를 차지하게 됩니다.

 

(function() {
  
  console.log(variable);
  
  var variable = 'hoisted';
})();

 

호이 스팅 예제입니다. console 출력문이 변수 선언 및 할당 문 보다 먼저 실행되었고 에러가 발생할 것 같지만 undefined가 출력됩니다

런타임 이전에 변수 선언 부분만 마치 끌어져 올려진 것처럼 동작하기 때문입니다
호이스트는 건축에서 크레인으로 끌어져 올려지는 것으로 알고 있습니다.

 

(function() {
  if (true) {   
    var variable = 'function scope';
  }
  
  console.log(variable);
})();

함수 레벨 스코프입니다.
if 문에 포함되지 않음에도 if 문에서 할당된 변수에 참조가 가능합니다. 이는 예기치 못한 에러를 유발합니다.

 

위의 4가지 상황 이외에도 var 키워드는 전역에 선언된 것처럼 동작하여 말 그대로 전역 변수의 문제점을 갖습니다.

 

1. 긴 생명 주기
2. 스코프 체인상 종점에 존재
3. 네임스페이스 오염

 

변수는 스코프의 따라 유효한 범위를 갖게 되는데 전역 변수는 애플리케이션 전체의 유효 범위를 가지므로 늦게까지 메모리에서 제거가 되지 않습니다. 공간 낭비 및 에러 유발을 가져오며,

변수를 참조하는 과정에서도 스코프 체인의 종점에 존재하여 늦게 검색하게 됩니다.

또한 파일들이 분리되어 1.js 2.js 등 여러 개의 파일이 있어도 변수명은 공유되므로
다시 에러를 유발할 수 있습니다.

 

위와 같은 문제를 해결한 게 let 키워드이며
1. 블록 레벨 스코프
2. 중복 선언 금지
3. 호이 스팅이 동작하지 않는 것처럼 동작
4. let은 변경 가능 const는 변경 불가능(재할당)을 특징으로 합니다.

// 1. 블록 레벨 스코프
{
  let variable = 'block scope';
  console.log(variable);
}

// 2. 중복 선언 => SyntaxError
{
  let variable = 'block scope';
  let variable = 'duplicated';
  console.log(variable);
}

// 3. 호이스팅 => ReferenceError
{
  console.log(variable);
  let variable = 'hoisted';
}
//4. let은 변경가능 const는 변경불가능

// Primitive
let a = 'a';
a = 'b';
a;

const c = 'c';
c = 'd'; // TypeError
c;


let e = {
  foo: 'foo',
};
e = {
  bar: 'bar',
};
e;

const f = {
  foo: 'foo',
};
// f = {
//   foo: 'bar',
// }; TypeError
f.foo = 'bar';
f;

 

es6 이후 var 키워드는 사용하지 않고, let과 const 키워드만 사용합니다.

let과 const를 어떤 비율로 사용하나요?라고 묻는다면 기본적으로 const를 사용하되 꼭 변경이 가능할 때만 let을 사용해야 한다고 말하고 싶으며 let을 사용했다면 const로 변경 가능할 일이 없게 만들 수 없는지 고민하고
const 키워드를 주로 사용하여 변수의 안정성을 높이라고 말하고 싶습니다.

 

let이 호이 스팅을 발생하지 않는 것처럼 동작한다고 하였습니다.

 

let 키워드로 선언한 변수는 선언 단계와 초기화 단계가 분리되며

 

런타임 이전에 자바스크립트 엔진에 의해 암묵적으로 선언 단계가 먼저 실행되지만 초기화 단계는 변수 선언문에 도달했을 때 실행됩니다.

 

만약 초기화 단계가 실행되기 이전에 변수에 접근하려고 하면 참조 에러(ReferenceError)가 발생합니다

 

let 키워드로 선언한 변수는 스코프의 시작 지점부터 초기화 단계 시작 지점(변수 선언문)까지 변수를 참조할 수 없습니다.

 

스코프의 시작 지점부터 초기화 시작 지점까지 변수를 참조할 수 없는 구간을 일시적 사각지대라고 합니다.

 

let foo = 1; // 전역 변수

{
  console.log(foo); // ReferenceError: Cannot access 'foo' before initialization
  let foo = 2; // 지역 변수
}

let 키워드로 선언한 변수의 경우, 변수 호이 스팅이 발생하지 않는다면 위 예제는 전역 변수 foo의 값을 출력해야 합니다

 

하지만 let 키워드로 선언한 변수도 여전히 호이스팅이 발생하기 때문에 참조 에러(ReferenceError)가 발생합니다.

 

자바스크립트는 ES6에서 도입된 let, const를 포함해서 모든 선언(var, let, const, function, function*, class 등)을 호이 스팅 합니다.

 

단, ES6에서 도입된 let, const, class를 사용한 선언문은 호이 스팅이 발생하지 않는 것처럼 동작합니다.

 

주관적으로 var 키워드는 더 이상 사용하지 않기 때문에 var 키워드의 단점을 이해했는가를 문제의 핵심으로 추측해보았습니다.

 


var의 단점:

  • 함수 레벨 스코프
  • var 키워드 생략 허용
  • 변수 중복 선언 허용
  • 변수 호이스팅
  • 긴 생명주기
  • 암묵적 결합
  • 스코프 체인 상 종점에 위치
  • 네임스페이스 오염 외우려 하지 마세요, 왜냐 var 키워드는 더 이상 사용하지 않고, 자바스크립트 언어를 이해한다면 자연스러운 이야기니까요.

파생되는 예상 질문

호이 스팅이란? -> 호이스팅 편 참조 함수 레벨, 블록 레벨 스코프란? 스코프 편 참조

 

var는 안 쓰고 let, const 쓴다고 하셨는데 재할당 여부를 모른다면 어떻게 사용하시나요?

 

저는 const를 먼저 사용해서 코딩을 한 후, 최대한 재할당을 피하되, 피할 수 없는 경우 let을 사용하는 방식을 쓰고 있습니다.

반응형

'1.웹개발 > JS' 카테고리의 다른 글

변수와 메모리 적재 과정  (0) 2022.01.25
for문의 동작순서  (0) 2020.10.13
[JS] 자바스크립트 ES5 ES6 차이  (2) 2019.08.12
[JS] 019-017이 4인 이유  (0) 2019.06.02
[JS]this,바인딩,this결정조건  (0) 2019.05.14