var, let, const

raccoonback·2020년 6월 12일
1

javascript

목록 보기
2/11
post-thumbnail

varFunction-Level Scope를 가지고, letconstBlock-Level Scope를 가진다.

Function Scope부터 하나씩 살펴보자.

Function Scope

function scope 란 함수에서 선언된 변수는 내부에서만 유효하고, 외부에서는 참조할 수 없다는 의미이다.

function test() {
    var a = 1;
    if(true) {
        var b = 2;
        if(true) {
            var c = 3;
        }
    }

    console.log(a, b, c);
}

test();
console.log(a, b, c);

위와 같이, test() 함수를 호출한 결과는 무엇일까? 정답은 1 2 3 과 마지막 console.log() 함수는 a, b, c 변수를 참조하지 못한다.

그 이유는 a, b, ctest() 함수 내부에서 유효한 동일한 scope를 가지고 있기 때문이다. 그리고 함수 밖인 전역 스코프에서는 a, b, c 변수가 없으므로 접근할 수 없는 것이다.

여기서 한가지 더 짚고 넘어갈게 있다. 렉시컬 스코프이다.

렉시컬 스코프

렉시컬 스코프는 함수의 실행 환경이 아닌 함수를 정의한 환경으로 참조하는 특징을 가지고 있다. 말이 어려우므로 예제를 통해서 살펴보자.

var a = 0;

function first() {
    var a = 1;
    second();
}

function second() {
    console.log(a);
}

first();

예상을 해보면, 우선 second() 함수가 호출될 시점에 상위 스코프인 first() 함수 스코프를 참조해 '1'을 출력할 것이라고 생각할 수 있다. 하지만, 자바스크립트는 렉시컬 스코프의 정의에 따라 함수 호출 시점이 아닌 함수를 선언한 위치에 따라 상위 스코프가 결정된다. 따라서 second() 함수는 전역 스코프에서 선언이 되었고 상위 스코프는 전역 스코프가 되어 '0'이 출력된다.

그럼 아래 코드는 어떻게 출력이 될 지 짐작이 될 것이다.

var a = 0;

function first() {
    var a = 1;
		var second = function() {
	    console.log(a);
		}
    second();
}

first();

second 함수는 first() 함수 내부에 선언되어 상위 스코프는 first() 함수 스코프이고 '1'을 출력할 것이다.

var 키워드 생략된 경우

뜬금없지만, 만약 var 를 선언하지 않는다면 어떻게 될까?

해당 변수는 전역 스코프에 선언이 된다.

function first() {
    var second = function () {
        a = 1;

    }
    second();
}

first();
console.log(a);

Block scope

var는 Function Scope로 많은 유연함을 제공했지만, 그로 인한 복잡성도 공존하고 있었다.

특히, 아래와 같은 재선언 가능, Function Scope에서의 호이스팅 에 대한 복잡함이 있었다.

var a = 1;
var a = 2; // 에러 안남;;

b = 3;
var b; // hoisting 으로 인해 에러 발생하지 않음;;

따라서 ES6 이후 Block-Level Scope라는 개념을 가진 let, const이 추가되었다. 물론 let, const생성, 실행 단계를 거치기 때문에 Hoisting이 발생하지만, Block Scope 안에서 호이스팅이 발생하기 때문에 보다 엄격하게 변수를 선언할 수 있게 되었다.

또한, var 과 다르게 letconst 는 재선언시, Reference Error 가 발생한다.

Block Scope 가지는 let, const{} 기준으로 Function Scope와 다르게 if, for, while, try/catch 문과 같은 문법에서 유용하게 사용될 수 있다.

let

let은 변수에 재할당을 할 수 있다.

하지만, var와 같이 선언 이전에 참조를 하게 되면 Reference Error가 발생한다.

console.log(foo) // Reference Error

let foo = 1;
console.log(foo); // 1

foo = 2;
console.log(foo); // 2

for(let item of [1, 2, 3]) {
	console.log(item); // 1, 2, 3
}

위 예제와 같이, 이미 선언한 변수에 값을 재할당할 수도 있고, 반복문은 Block 스코프를 가지게 된다.

const

const선언 이전에 참조를 하게 되면 Reference Error가 발생한다.

let 과 차이점은 변수에 재할당을 할 수 없고, 선언과 동시에 할당해야만 한다. 즉, 불변성을 보장한다.

console.log(foo) // Reference Error

const foo = 1;
console.log(foo); // 1

foo = 2; // Assignment to constant variable.

const 변수에 재할당하게 되면 에러가 발생한다.

profile
한번도 실수하지 않은 사람은, 한번도 새로운 것을 시도하지 않은 사람이다.

0개의 댓글