2월 4일 (금) var, let, const의 차이점과 호이스팅(Hoisting)

남이섬·2022년 2월 4일
0

var, let, const 차이점

var는 function-scoped 이고 let, const는 block-scoped이다

var

1. 중복선언이 가능하다

마지막에 할당된 값이 변수에 저장된다
초기화 없이 선언만 한 경우엔 선언문 자체가 무시된다

// 첫번째 변수 선언+초기화 var a = 10;
console.log(a); // 10

// 두번째 변수 선언+초기화 var a = 20;
console.log(a); // 20

// 세번째 변수 선언(초기화X) var a;
console.log(a); // 20

2. 값의 재할당이 가능하다

let a = 1;
a = 2;
console.log(a); // 2

let

1. 중복선언 불가능

let 중복 선언
let a = 10; let a = 20; // SyntaxError: Identifier 'a' has already been declared

2. 값의 재할당이 가능하다

let b = 1;
b = 2;
console.log(b); // 2

const

1. 중복선언 불가능

const 중복 선언
const b = 10;
const b = 20; // SyntaxError: Identifier 'b' has already been declared

2. 값의 재할당이 불가능하다

const는 상수를 선언하는 키워드다 (상수는 변하지 않고 항상 같은 값을 가지는 수를 말한다)

const c = 1;
c = 2; // TypeError: Assignment to constant variable.

const는 처음 선언할 때 반드시 값을 할당 해주어야 한다

const a = 10;
const b; // SyntaxError: Missing initializer in const declaration

스코프(Scope)

스코프란 유효한 참조 범위를 말한다
예를 들어, 함수 내부에서 선언된 변수는 함수 내부에서만 참조가 가능하다.
이 경우 변수의 스코프는 함수 내부로 한정 된다.

전역 스코프(Global Scope) & 지역 스코프 (Local Scope)

  • 전역 스코프는 블록{} 바깥이나 함수 바깥에 선언 된 변수
  • 지역 스코프는 코드의 특정 부분에서만 사용할 수 있는 변수, 지역 스코프는 함수 스코프와 블록 스코프 두 가지로 나뉜다

1. 함수 레벨 스코프 (function-level scope)

함수 내부에 선언된 변수만 지역변수로 한정하며, 나머지는 모두 전역변수로 간주한다

var

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로 선언된 변수를 전역 변수로 간주한다

그래서 블럭 외부에서도 어디에서나 참조할 수 있다

2. 블록 레벨 스코프 (block-level scope)

let, const는 함수 내부는 물론, if문이나 for문 등의 코드 블럭{ ... } 에서 선언된 변수도 지역변수로 취급한다

let, const

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문 등에서 중괄호{ } 로 둘러싸인 코드 영역을 말한다

호이스팅 (Hoisting)

함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것

  • 자바스크립트 함수는 실행되기 전에 함수 안에 필요한 변수값들을 모두 모아서 유효 범위의 최상단에 선언한다
    • 자바스크립트 parser가 함수 실행 전 해당 함수를 한 번 훑는다
    • 함수 안에 존재하는 변수/함수선언에 대한 정보를 기억하고 있다가 실행시킨다
    • 유효 범위: 함수 블록{} 안에서 유효
  • 즉, 함수 내에서 아래쪽에 존재하는 내용 중 필요한 값들을 끌어올리는것
    • 실제로 코드가 끌어올려지는 건 아니며, 자바스크립트 parser 내부적으로 끌어올려서 처리하는 것
    • 실제 메모리에는 변화가 없다

대상

  • var 변수 선언과 함수선언문에서만 호이스팅이 일어난다
    • 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
profile
즐겁게 살자

0개의 댓글