
var, let, const의 차이점 - 변수 선언 및 할당, 호이스팅
자바스크립트에선 변수선언 가능한것이 var, let, const 이 세가지가 있다.
그럼 이 세개의 차이는 무엇일까?
일단 변수란 ? 변수는 하나의 특정한 값을 저장하는 메모리 공간을 뜻한다.
이 메모리 공간에 저장되는건 정수형 / 실수형 / 문자 및 문자열 등 여러가지가 있다.
const number = 10
// 변수명(식별자) : number
// 해당 값의 위치(메모리주소): 0012CCGWH80
// 변수값(저장된 값) : 10
자바스크립트는 매니지드 언어(managed language)이기 때문에 개발자가 직접 메모리를 제어하지 못한다.
따라서 개발자가 직접 메모리 주소를 통해 값을 저장하고 참조할 필요가 없고 변수를 통해 안전하게 값에 접근이 가능하다.
변수명(식별자)인 number는 변수의 값이 아닌 메모리 주소를 기억하고 있다.
변수명을 사용하면, 자바스크립트 엔진이 변수명과 매핑된 메모리 주소를 통해 거기에 저장된 값(23)을 반환한다.
이처럼 변수에 값을 저장하는 것을 할당(assignment, 대입, 저장)이라 하며 변수에 저장된 값을 읽어 들이는 것을 참조(reference)라 한다.
그리고 변수명을 자바스크립트 엔진에 알리는 것을 선언(declaration)이라 한다.
변수의 선언은 var, const, let 키워드로 할 수 있으며, ES6에서 const와 let이 var의 키워드의 단점을 보완하여 새로 추가되었다.
자바스크립트에서 변수 선언은 선언 → 초기화 단계를 거쳐 수행된다.
var study
console.log(study)
// 결과값 = undefined
var 키워드를 이용한 변수 선언은 선언 단계와 초기화 단계가 동시에 진행되어, study에 암묵적으로 undefined를 할당해 초기화한다.
그런데 반대로, console을 먼저 찍어도 반환 값이 undefined로 나온다.
console.log(study)
var study
// 결과값= undefined
이는 변수 선언이 런타임에서 되는 것이 아니라, 그 이전 단계에서 먼저 실행되기 때문이다.
자바스크립트 엔진은 소스코드를 한 줄씩 순차적으로 실행하기에 앞서,
변수 선언을 포함한 모든 선언문(ex. 변수 선언문, 함수 선언문 등)을 찾아내 먼저 실행한다.
즉, 변수 선언이 어디에 있든 상관없이 다른 코드보다 먼저 실행되는 특징을 호이스팅(hoisting)이라 한다.
변수 선언 뿐만 아니라, var, let, const, function, function*, class 키워드를 사용해 선언한 모든 식별자(변수, 함수, 클래스 등)는 호이스팅이 된다.
간단히 말하면 선언방식의 차이이다.
var name = 'javascript'
console.log(name)
//결과값 = javascript
var name = 'study'
console.log(name)
//결과값 = study
변수를 한번 더 선언했음에도 불구하고 결과값이 에러가 나오지않고 2개의 다른값이 출력된다.
이것은 간단하게 테스트에는 좋으나, 수많은 코드가 있으면 값이 바뀔 우려가 있고,
사용되는 위치를 모르는 상황이 생겨버린다.
그래서 이것을 보완하기 위해 나온것이 let과 const 이다.
그렇다면 똑같은 방법으로 let 그리고 const로 바꾸면 어떻게될까?
let name = 'javascript'
console.log(name)
//결과값 = javascript
let name = 'study'
console.log(name)
//결과값= Uncaught SyntaxError: Identifier 'name' has already been declared
❓ 그렇다면 똑같은 오류가 뜨는데 let과 const 의 차이는 무엇일까??
앞서 말한 내용에서 설명할수있다.
let name = 'javascript'
console.log(name)
//결과값 = javascript
let name = 'study'
console.log(name)
//결과값= Uncaught SyntaxError: Identifier 'name' has already been declared
name = 'react'
console.log(name)
//결과값 = react
위의 내용에서 let은 재할당이 가능하다. 하지만
const name = 'javascript'
console.log(name)
//결과값 = javascript
const name = 'study'
console.log(name)
//결과값= Uncaught SyntaxError: Identifier 'name' has already been declared
name = 'react'
console.log(name)
//결과값 = Uncaught TypeError: Assignment to constant variable.
각각의 이러한 차이가 있다.
위에서 function 키워드로 선언한 모든 식별자도 호이스팅이 된다고 했는데, 그렇다면 정확히 어떻게 이루어질까?
먼저 함수가 정의되는 방식 네 가지를 살펴보자.
// 1. 함수 선언문
// 함수 이름 생략 불가능
function add(x, y) {
return x + y
}
// 2. 함수 표현식
// 함수 이름 생략 가능
var add = function(x, y) {
return x + y
}
// 함수 이름 작성 시,
// var add = function plus(x, y) {
// return x + y
// }
// 3. Function 생성자 함수
var add = new Function('x', 'y', 'return x+ y')
// 4. 화살표 함수
var add = (x, y) => x + y
위에서 함수 선언문과 함수 표현식의 호이스팅 결과를 먼저 보자.
// 함수 참조
console.dir(add) // 결과값= f add(x, y)
console.dir(sub) // output: undefined
// 함수 호출
console.log(add(2, 5)) // output: 7
console.log(sub(2, 5)) // output: Uncaught TypeError: sub is not a function
// 함수 선언문
function add(x, y) {
return x + y
}
// 함수 표현식
var sub = function(x, y) {
return x + y
}
함수 선언문의 경우,
런타임 이전에 자바스크립트 엔진에서 먼저 실행되어, 함수 자체를 호이스팅 시킬 수 있다.
반면, 함수 표현식은 위에서 봤던 변수 호이스팅과 같이 런타임 이전에 해당 값을 undefined로 초기화만 시키고,
런타임에서 해당 함수 표현식이 할당되어 그때 객체가 된다.