[JavaScript] var, let, const 그리고 Hoisting

ImOk·2021년 12월 7일
1

👩‍💻 웹 개발

목록 보기
5/14
post-thumbnail
post-custom-banner

1. var

  • function level scope를 갖는다. 따라서 전역 함수 외부에서 생성한 변수는 모두 전역 변수이다.
  • 키워드는 생략이 가능하다.
  • 재선언재할당가능하다.
  • Hoisting 당한다.
var t = "javascript"
console.log(t);  // javascript

var t = "JAVA"
console.log(t);  // JAVA

1-1. 함수(function) 에서의 유효 범위 (scope)

var a1 = 1; // 전역변수
var a2 = 2;
function printVar() {
    var a1 = 10;
    a2 = 20;
    var a3 = 30; // 지역변수
    console.log('a1 : ' + a1 + ', a2 : ' + a2 + ', a3 : ' + a3); 
      				// a1 : 10, a2 : 20, a3 : 30
}
console.log('a1 : ' + a1); // a1 : 1
console.log('a2 : ' + a2); // a2 : 2
printVar();
console.log('a1 : ' + a1); // a1 : 1
console.log('a2 : ' + a2); // a2 : 20
console.log('a3 : ' + a3); // ReferenceError: a3 is not defined

a3는 function 내에서 선언됐기 때문에, function level scope 밖에서 error 발생.


1-2. if 조건문 에서의 유효 범위 (scope)

var a1 = 1; // 전역변수
var a2 = 2;
if (true) {
    var a1 = 10;
    a2 = 20;
    var a3 = 30; // 전역변수
    console.log('a1 : ' + a1 + ', a2 : ' + a2 + ', a3 : ' + a3); 
  				// a1 : 10, a2 : 20, a3 : 30
}
console.log('a1 : ' + a1); // a1 : 10
console.log('a2 : ' + a2); // a2 : 20
console.log('a3 : ' + a3); // a2 : 30

1-3. for 반복문 에서의 유효 범위 (scope)

var a1 = 1; // 전역변수
var a2 = 2;
for (a1; a1 < 2; a1++) {
    a2 = 20;
    var a3 = 30; // 전역변수
    console.log('a1 : ' + a1 + ', a2 : ' + a2 + ', a3 : ' + a3); 
  				// a1 : 1, a2 : 20, a3 : 30
}
console.log('a1 : ' + a1); // a1 : 2
console.log('a2 : ' + a2); // a2 : 20
console.log('a3 : ' + a3); // a2 : 30

2. let

  • {block level scope} 를 갖는다. 따라서 블록 내에서 선언된 변수는 지역변수이므로 블록 내에서만 유효하며, 블록 외부에서는 참조할 수 없다.
  • 키워드 생략이 불가능하다.
  • 재선언불가능하다.
  • 재할당가능하다.
  • Hoisting 당한다.
let t = "javascript"
console.log(t);  // javascript

let t = "JAVA"	 // (재선언 X)
console.log(t);  // Uncaught SyntaxError: Identifier 't' has already been declared

t = "JAVA"	 // (재할당 O)
console.log(t);  // JAVA

2-1. 함수(function) 에서의 유효 범위 (scope)

let a1 = 1; // 전역변수
let a2 = 2;
function printVar() {
    let a1 = 10;
    a2 = 20;
    let a3 = 30; // 지역변수
    console.log('a1 : ' + a1 + ', a2 : ' + a2 + ', a3 : ' + a3); 
  				// a1 : 10, a2 : 20, a3 : 30
}
console.log('a1 : ' + a1); // a1 : 1
console.log('a2 : ' + a2); // a2 : 2
printVar();
console.log('a1 : ' + a1); // a1 : 1
console.log('a2 : ' + a2); // a2 : 20
console.log('a3 : ' + a3); // ReferenceError: a3 is not defined

a3는 function 내에서 선언됐기 때문에, block level scope 밖에서 error 발생.


2-2. if 조건문 에서의 유효 범위 (scope)

let a1 = 1; // 전역변수
let a2 = 2;
if (true) {
    let a1 = 10; // 지역변수
    a2 = 20;
    let a3 = 30; // 지역변수
    console.log('a1 : ' + a1 + ', a2 : ' + a2 + ', a3 : ' + a3); 
  				// a1 : 10, a2 : 20, a3 : 30
}
console.log('a1 : ' + a1); // a1 : 1
console.log('a2 : ' + a2); // a2 : 20
console.log('a3 : ' + a3); // ReferenceError: a3 is not defined

a3는 if문 내에서 선언됐기 때문에, block level scope 밖에서 error 발생.


2-3. for 반복문 에서의 유효 범위 (scope)

let a1 = 1; // 전역변수
let a2 = 2;
for (a1; a1 < 2; a1++) {
    a2 = 20;
    let a3 = 30; // 지역변수
    console.log('a1 : ' + a1 + ', a2 : ' + a2 + ', a3 : ' + a3); 
  				// a1 : 1, a2 : 20, a3 : 30
}
console.log('a1 : ' + a1); // a1 : 2
console.log('a2 : ' + a2); // a2 : 20
console.log('a3 : ' + a3); // ReferenceError: a3 is not defined

a3는 for문 내에서 선언됐기 때문에, block level scope 밖에서 error 발생.


3. const

  • {block level scope} 를 갖는다
  • 재선언재할당불가능하다.
  • const는 선언과 동시에 할당이 이루어져야 한다.
  • 상수를 선언할 때 사용한다.
  • Hoisting 당한다.
const t = "javascript"
console.log(t);  // javascript

const t = "JAVA" // (재선언 X)
console.log(t);  // Uncaught SyntaxError: Identifier 't' has already been declared

t = "JAVA"	 // (재할당 X)
console.log(t);  // Uncaught TypeError: Assignment to constant variable.

3-1. 함수(function) 에서의 유효 범위 (scope)

const a1 = 1; // 전역변수
const a2 = 2;
function printVar() {
    const a1 = 10; // 지역변수
    a2 = 20; // TypeError: Assignment to constant variable.
    const a3 = 30; // 지역변수
    console.log('a1 : ' + a1 + ', a2 : ' + a2 + ', a3 : ' + a3);
    				// a1 : 10, a2 : 2, a3 : 30
}
console.log('a1 : ' + a1); // a1 : 1
console.log('a2 : ' + a2); // a2 : 2
printVar();
console.log('a1 : ' + a1); // a1 : 1
console.log('a2 : ' + a2); // a2 : 2
console.log('a3 : ' + a3); // ReferenceError: a3 is not defined

a2는 재할당 불가로 error 발생
a3는 function 내에서 선언됐기 때문에, block level scope 밖에서 error 발생.


3-2. if 조건문 에서의 유효 범위 (scope)

const a1 = 1; // 전역변수
const a2 = 2;
if (true) {
    const a1 = 10; // 지역변수
    a2 = 20; //TypeError: Assignment to constant variable.
    const a3 = 30; // 지역변수
    console.log('a1 : ' + a1 + ', a2 : ' + a2 + ', a3 : ' + a3);
    				// a1 : 10, a2 : 2, a3 : 30
}
console.log('a1 : ' + a1); // a1 : 1
console.log('a2 : ' + a2); // a2 : 2
console.log('a3 : ' + a3); // ReferenceError: a3 is not defined

a2는 재할당 불가로 error 발생
a3는 if문 내에서 선언됐기 때문에, block level scope 밖에서 error 발생.


3-3. for 반복문 에서의 유효 범위 (scope)

const a1 = 1; // 전역변수
const a2 = 2;
for (b1 = 1; b1 < 2; b1++) {
    const a1 = 10;
    a2 = 20; //TypeError: Assignment to constant variable.
    const a3 = 30; // 지역변수
    console.log('a1 : ' + a1 + ', a2 : ' + a2 + ', a3 : ' + a3); 
  				// a1 : 10, a2 : 2, a3 : 30
}
console.log('a1 : ' + a1); // a1 : 1
console.log('a2 : ' + a2); // a2 : 2
console.log('a3 : ' + a3); // ReferenceError: a3 is not defined

a2는 재할당 불가로 error 발생
a3는 for문 내에서 선언됐기 때문에, block level scope 밖에서 error 발생.


4. Hoisting

  • 모든 변수 선언은 Hoisting 된다.
  • 변수의 정의가 그 범위에 따라 선언할당으로 분리되는 것
  • 변수가 함수내에 정의되었을 경우 : 선언이 함수의 최상위로, 함수 바깥에서 정의되었을 경우 : 전역 컨텍스트의 최상위로 변경
  • " scope 안에 있는 선언들을 모두 scope의 최상위로 끌어올리는 것 "

4-1. var

  • 선언과 초기화가 한 번에 이루어짐. 즉, 스코프에 변수를 선언하고 메모리에 변수를 위한 공간을 확보한 후 undefined로 초기화한다.
console.log("1 : " + t);  // 1 : undefined => '선언','초기화'
// => 최상위로 Hoisting, 할당은 이후에 발생하기 때문에, 이 시점은 undefined

var t = "javascript"
console.log("2 : " + t);  // 2 : javascript => '할당'

4-2. let

  • 선언과 초기화가 분리되어 이루어짐. 즉, 스코프에 변수를 선언하지만 초기화 단계는 변수 선언 시 이루어진다.
  • 스코프 시작 지점부터 초기화 시작 지점까지 구간을 일시적 사각지대(Temporal Dead Zone)라고 부른다.
/////////////////////Temporal Dead Zone/////////////////////////
console.log("1 : " + t);  // Uncaught ReferenceError: Cannot access 't' before initialization => '선언'
////////////////////////////////////////////////////////////////
let t;
console.log("2 : " + t);  // 2 : undefined => '초기화'

t = "JAVA"
console.log("3 : " + t);  // 3 : JAVA => '할당'

4-3. const

  • let과 마찬가지로 선언 전에 사용하면 ReferenceError 발생
console.log("1 : " + t); // Uncaught ReferenceError: Cannot access 't' before initialization

const t = "JAVA" ;
console.log("2 : " + t); // 2 : JAVA => '선언', '할당'

🔗 참고 자료

https://poiemaweb.com/js-execution-context
https://dmitripavlutin.com/variables-lifecycle-and-why-let-is-not-hoisted/

profile
ImOk👌
post-custom-banner

0개의 댓글