var
는 function-scoped 이고 let
, const
는 block-scoped이다
마지막에 할당된 값이 변수에 저장된다
초기화 없이 선언만 한 경우엔 선언문 자체가 무시된다
// 첫번째 변수 선언+초기화 var a = 10;
console.log(a); // 10// 두번째 변수 선언+초기화 var a = 20;
console.log(a); // 20// 세번째 변수 선언(초기화X) var a;
console.log(a); // 20
let a = 1;
a = 2;
console.log(a); // 2
let 중복 선언
let a = 10; let a = 20; // SyntaxError: Identifier 'a' has already been declared
let b = 1;
b = 2;
console.log(b); // 2
const 중복 선언
const b = 10;
const b = 20; // SyntaxError: Identifier 'b' has already been declared
const는 상수를 선언하는 키워드다 (상수는 변하지 않고 항상 같은 값을 가지는 수를 말한다)
const c = 1;
c = 2; // TypeError: Assignment to constant variable.
const는 처음 선언할 때 반드시 값을 할당 해주어야 한다
const a = 10;
const b; // SyntaxError: Missing initializer in const declaration
스코프란 유효한 참조 범위를 말한다
예를 들어, 함수 내부에서 선언된 변수는 함수 내부에서만 참조가 가능하다.
이 경우 변수의 스코프는 함수 내부로 한정 된다.
함수 내부에 선언된 변수만 지역변수로 한정하며, 나머지는 모두 전역변수로 간주한다
function hello(){ var a = 10; console.log(a); } hello(); // 10 console.log(a); //ReferenceError: a is not defined
hello 함수 내부에서 선언된 a변수는 함수 내부에서만 참조가 가능하며, 외부에서 참조시 에러가 발생한다
if(true) { var a = 10; console.log(a); // 10 } console.log(a); // 10
함수를 제외한 영역에서 var로 선언한 변수는 '전역변수'로 취급된다
자바스크립트애서는 if문, for문, while문, try/catch 문 등의 코드 블럭{ ... } 내부에서 var로 선언된 변수를 전역 변수로 간주한다
그래서 블럭 외부에서도 어디에서나 참조할 수 있다
let, const는 함수 내부는 물론, if문이나 for문 등의 코드 블럭{ ... } 에서 선언된 변수도 지역변수로 취급한다
if(true) { let a = 10; console.log(a); // 10 } console.log(a); // ReferenceError: a is not defined
if문의 블럭 내부에서 let으로 선언된 변수는 외부에서 참조되지 않음을 알 수 있다
function hello() { let a = 10; console.log(a); // 10 } console.log(a); // ReferenceError: a is not defined
함수 내부에서 선언된 변수도 외부에서 참조할 수 없다
var
는 함수 내부에 선언된 변수만 지역 변수로 인정하는 함수 레벨 스코프
이다
let, const
는 블록 내부에서 선언된 변수까지도 지역변수로 인정하는 블록 레벨 스코프
이다
참고로 블록은 if문이나 for문 등에서 중괄호{ } 로 둘러싸인 코드 영역을 말한다
함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것
var
변수/함수의 선언만 위로 끌어 올려지며, 할당은 끌어 올려지지 않는다let
/const
변수 선언과 함수표현식에서는 호이스팅이 발생하지 않는다console.log("hello"); // hello console.log(myname); // undefined console.log(myname2); // Uncaught ReferenceError: Cannot access 'myname2' before initialization var myname = "HEEE"; // var 변수 let myname2 = "HEEE2"; // let 변수
호이스팅
은 함수선언문
과 함수표현식
에서 서로 다르게 동작 하기 때문에 주의해야 한다function printName(firstname) { // 함수선언문 var result = inner(); // "선언 및 할당" console.log(typeof inner); // > "function" console.log("name is " + result); // > "name is inner value" function inner() { // 함수선언문 return "inner value"; } } printName(); // 함수 호출
호이스팅 과정
function printName(firstname) { // 함수선언문 function inner() { // 함수선언문 // 2번 호이스팅 return "inner value"; } var result = inner(); // "선언 및 할당" // 1번 호이스팅 console.log(typeof inner); // "function" console.log("name is " + result); // "name is inner value" } printName(); // 함수 호출
var number = 1; function numberString() { console.log("1"); } function boolean() { console.log(true); } var string = "hi"; console.log(typeof number); // number console.log(typeof string); // string // var 선언문 먼저 호이스팅 된다
var myName = "TS"; // 값 할당 var yourName; // 값 할당 X function myName() { // 같은 이름의 함수 선언 console.log("myName Function"); } function yourName() { // 같은 이름의 함수 선언 console.log("yourName Function"); } console.log(typeof myName); // "string" console.log(typeof yourName); // "function"
- 값이 할당되어 있지 않은 변수의 경우, 함수선언문이 변수를 덮어쓴다
- 값이 할당되어 있는 변수의 경우, 변수가 함수선언문을 덮어쓴다
let, const로 선언 했을 때
let myName = "TS"; // 값 할당 let yourName; // 값 할당 X function myName() { // 같은 이름의 함수 선언 console.log("myName Function"); } function yourName() { // 같은 이름의 함수 선언 console.log("yourName Function"); } console.log(typeof myName); console.log(typeof yourName); // Uncaught SyntaxError: Identifier 'myName' has already been declared