JavaScript 변수들의 차이점에 대해 알아보자!
처음 공부할 때 접하는 변수 선언 방식
가볍게만 알고 있었던 변수들의 특징에 대해 알고 가자
1-1var
var hello='first hello';
var hello='second hello';
console.log(hello); // second hello
위 코드를 보면
var
의 특징 중 하나로 변수 중복 선언이 가능하다.
같은 변수를 여러번 선언해도 오류가 나지 않고 각기 다른 값이 출력될 수 있다.
대부분의 문제는 전역 변수로 인해 발생한다.
이런식의 유연한 변수 선언 방식은 편리하다는 장점도 있지만, 의도하지 않은 변수값의 변경이 일어나는 등 많은 오류를 발생시키기도 했습니다.
그래서 ES6 이후, var
의 단점을 보완하기 위해 추가 된 변수 선언 방식이 let
과 const
이다.
1-2 let
var
처럼 같은 변수를 두 번 선언하는 것은 불가)let hello='first hello';
let hello='second hello';
// 변수 중복 선언 안됨
console.log(hello) // Error
Hollo = 'third hello';
// 변수에 재할당은 가능
console.log(Hollo) // third hello
1-3 const
const
는 'constance'의 약자로 상수를 선언한다.
한번 선언된 상수는 다시 재정의 할 수 없다.
conts hello='hello';
hello='hello foo';
//const는 상수(변하지 않는 값)를 위해 사용한다.
console.log(hello) // Error
//선언과 동시에 할당안하면 에러
const foo; // SyntaxError: Missing initializer in const declaration
const는 선언과 동시에 할당이 이루어져야 한다.
2-1 var
var foo = 123; // 전역 변수
{
var foo = 456; // 전역 변수
}
console.log(foo); // 456
var
로 선언한 변수의 scope은 function이기 때문에
코드 블록{}
외부 변수 foo의 값이 재할당되어 변경된 것을 볼 수 있다.
하지만 함수내에서 선언된 변수는 함수내에서만 유효 함수 외부에서는 참조할수 없다.
var foo='hello!'
function helloFoo() {
var foo='hello in function!';
console.log(foo);
}
helloFoo(); // hello in function!
console.log(foo); // hello!
위의 코드를 보면 외부 변수 foo의 값이 재할당되지 않는다.
var
유효범위가 function안에서 적용된다는것을 알 수 있다.
for 문의 변수 선언문에서 선언한 변수를 for 문의 코드 블록 외부에서 참조할 수 있다.
for(var i=0; i<5; i++) {
console.log(i)
}
console.log('i is ', i);
function counter () {
for(var i=0; i<5; i++) {
console.log(i)
}
}
counter()
console.log('i is', i) // Error
2-2 let
,const
{}
의 scoped을 가진다.// 전역 변수
let foo = 123;
const hello='hello!';
{
// 지역 변수
let foo = 456;
let bar = 456;
const hello='hello foo';
console.log(hello); // hello foo
}
console.log(foo); // 123
console.log(bar); // ReferenceError: bar is not defined
console.log(hello); // hello!
const
은 상수이지만
const
의 scope은 코드 블록 내부이기 때문에
코드 블록 외부에 상수를 또 선언할 수 있습니다.
호이스팅(Hoisting)이란, var
선언문이나 function
선언문 등을 해당 스코프의 선두로 옮긴 것처럼 동작하는 특성을 말한다.
자바스크립트는 ES6에서 도입된 let, const를 포함하여 모든 선언(var, let, const, function, function*, class)을 호이스팅한다.
var
, 함수
의 선언만 위로 끌어 올려지며, 할당은 끌어 올려지지 않는다.let
,const
변수 선언과 함수표현식에서는 호이스팅이 발생하지 않는다.console.log(foo); // undefined
var foo = 123;
console.log(bar); // Error: Uncaught ReferenceError: bar is not defined
let bar = 456;
위 코드에서 보면
var
로 선언된 변수와는 달리 let
로 선언된 변수를 선언문 이전에 참조하면 참조 에러(ReferenceError)가 발생한다.
foo(); // hello
foo2(); // Error
// 함수선언문
function foo() {
console.log("hello");
}
// 함수표현식
var foo2 = function() {
console.log("hello2");
}
함수 표현식에서는 호이 스팅어 발생하지 않아 오류가 뜨는 것을 볼 수 있다.
변수는 선언 단계
> 초기화 단계
> 할당 단계
에 걸쳐 생성되는데
var
키워드로 선언된 변수는 선언 단계와 초기화 단계가 한번에 이루어진다.
// 스코프의 선두에서 선언 단계와 초기화 단계가 실행된다.
// 따라서 변수 선언문 이전에 변수를 참조할 수 있다.
console.log(foo); // undefined
var foo;
console.log(foo); // undefined
foo = 1; // 할당문에서 할당 단계가 실행된다.
console.log(foo); // 1
let
키워드로 선언된 변수는 선언 단계와 초기화 단계가 분리되어 진행된다.
// 스코프의 선두에서 선언 단계가 실행된다.
// 아직 변수가 초기화(메모리 공간 확보와 undefined로 초기화)되지 않았다.
// 따라서 변수 선언문 이전에 변수를 참조할 수 없다.
console.log(foo); // ReferenceError: foo is not defined
let foo; // 변수 선언문에서 초기화 단계가 실행된다.
console.log(foo); // undefined
foo = 1; // 할당문에서 할당 단계가 실행된다.
console.log(foo); // 1