기록공간

JavaScript 변수 본문

FrontEnd/JavaScript

JavaScript 변수

입코딩 2021. 6. 8. 08:32
반응형

ES6가 나오면서 var 이외에도 let과 const 변수 키워드가 추가 되었다. 이 세가지의 특징은 무엇이며, 서로 어떠한 차이점이 있는지 알아보도록 하자.

 

var

var는 ES6 이전에 변수를 선언할 수 있는 유일한 키워드였다. var 키워드는 다음과 같은 특징이 있다. 

  • 함수레벨에서의 스코프로 구분
  • 변수 선언시 var 키워드 생략 가능
  • 중복 선언 허용 
  • 변수 호이스팅 (호이스팅은 뒤에서 설명..)

이러한 특징은 대부분 의도되지 않은 변수 사용을 초래할 뿐만 아니라 코드 복잡도를 높이는 원인이 된다. 이러한 단점을 보완하기 위해 ES6에서는 let과 const 키워드가 도입되었다.

 

let

지금부터 let의 특징을 알아보도록 하겠다. 

 

스코프(Scope)

대부분의 언어는 블록 레벨 스코프를 지원하지만 JavaScript에서는 함수레벨 스코프만을 지원하였다. 하지만 let과 const가 도입되면서 블록 레벨 스코프 변수를 지원할 수 있게 되었다. 특징은 다음과 같다.

  • 블록 레벨 스코프 (let, const)
    => 코드 블록 내부에서 선언한 변수는 코드 블록 내에서만 유효하며 외부에서 참조 불가능 
  • 함수 레벨 스코프 (var)
    => 함수 내부에서 선언한 변수는 지역 변수, 함수 외부에서 선언한 변수는 전역 변수
          함수 내부에서 선언한 변수는 함수 내에서만 유효하며 외부에서 참조 불가능

코드를 통해 확인해보도록 하겠다. 

var test = 'test';
console.log(test);    // test

{
    var test = 123;
}
console.log(test);    // 123

var 키워드는 함수 레벨 스코프로 돌아간다고 앞에서 설명했다. test 변수는 현재 어떠한 함수 블록 내에도 선언되어 있지 않기 때문에 전역 변수이다. 

let test1 = 'test';

{
    let test1 = 123;
    let test2 = 321;
}

console.log(test1); // test
console.log(test2); // Error

let 키워드로 선언된 변수는 블록 레벨 스코프로 작동한다. 그렇기 때문에 블록 안에서 선언된 test1과 test2는 블록 바깥에서는 값이 유효하지 않다. 그래서 블록 바깥에서 test2를 출력하려고 하면 에러를 띄우게 된다.

 

중복 선언 금지 

let 키워드는 var 키워드와는 다르게 중복 선언을 허용하지 않는다. 

var varTest = 'test';
var varTest = 123;      // 문제없이 잘 동작


let letTest = 'test';
let letTest = 123;     // Error

 

호이스팅

JavaScript의 또 다른 특징은 모든 선언(var, let, const, function 등)에 대해서 호이스팅한다. 호이스팅이란 선언을 해당 스코프의 선두로 옮겨서 동작하는 것처럼 만드는 특성이다.
(C언어에서 함수명을 미리 앞에 선언해놓고 내용은 뒤에 구현하는 것을 자동으로 해준다고 생각하면 된다)  

 

이러한 특징으로 다음과 같이 선언해도 오류가 발생하지 않는다.

console.log(test); // undefined(오류발생 X)

var test = 'hi!';

하지만 이 방법은 let에서 오류를 발생시키는데, 이는 var와 서로 생성 단계가 다르기 때문이다.

 

var는 선언/초기화가 한번에 이루어진다. 즉 변수객체에 변수를 등록하고 변수를 메모리에 할당하여 undefined로 초기화하는 과정이 한번에 이루어진다. 이러한 특성으로 에러가 발생하지 않는다.

console.log(test);   // ReferenceError

let test = 123;      

반면에 let은 선언과 초기화에 분리되어 진행된다. 따라서 let 키워드의 초기화는 변수 선언에 도달했을때 이루어지고, 초기화 이전에 변수에 접근할 경우에는 참조 에러(Reference Error)가 발생한다. 

 

클로저

클로저는 내부 함수가 외부 함수의 context에 접근할 수 있는 것을 의미한다. 흔히 함수 내에 함수를 정의하여 리턴하는 방식으로 사용한다. 내부 함수는 외부 함수의 파라미터, 지역변수 등을 외부 함수가 종료된 이후에도 사용할 수 있다. 이렇게 사용하는 변수를 자유 변수(free variable)라고 하며 자유 변수를 갖는 함수를 클로저라고 한다.

for(var i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i);
    }, 100);
}

위 코드는 0부터 9까지 출력하는 반복문처럼 보이지만 실행해보면 10이 열번 출력된다. 

setTimeout에 파라미터로 넘긴 function()은 0.1초 간격으로 실행되는데, 그 전에 반복문이 모두 순회하여 전역변수 i의 값이 10이 되기 때문이다. var 키워드로 선언한 변수 i는 함수 레벨 스코프로 동작하기 때문에 전역 스코프를 가지게 되어 이러한 문제가 발생하게 된다. 

 

이러한 문제를 해결하기 위해서 다음과 같이 클로저를 사용해준다.

for(var i = 0; i < 10; i++) {
    (function(index) {  // index는 자유변수
        setTimeout(function() {
            console.log(index);
        }, 100);
    }(i));
}

이렇게 하면 내부 함수는 반복문 동작에 따라서 별도로 10개의 스코프를 가지고, 외부 함수를 통해 파라미터로 받은 i 값도 각각 다른 값을 갖게 된다.

 

let 키워드를 사용하게 되면 클로저를 사용하지 않아도 동일한 결과를 확인할 수 있다.

for(let i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i);
    }, 100);
}

이렇게 제대로 동작할 수 있는 이유는, for문에서 let 키워드로 선언한 변수 i가 for문 내에서만 유효한 지역 변수이며 자유 변수로 동작하기 때문이다.

 

전역 객체와의 비교

JavaScript의 전역 객체는 모든 객체의 최상위 객체를 의미한다. 일반적으로 브라우저 사이드에서는 window 객체, 서버 사이드에서는 global 객체를 의미한다.

 

다음과 같이 var 키워드로 선언된 변수를 전역 변수로 사용하면 전역 객체의 프로퍼티가 된다.

var varVal = 123;   // 전역변수
console.log(window.varVal);    // 123

반면 let 키워드로 선언된 변수를 전역 변수로 사용하는 경우는 전역 객체의 프로퍼티가 아니게 된다.

let letVal = 123;   // 전역변수
console.log(window.letVal);   // undefined

 

const

let과 함께 도입된 const 키워드에 대해서 알아보자.

 

선언과 초기화

const는 상수를 위해 사용하는 키워드이고 가독성과 유지보수 편의를 위해 많이 사용한다. 하지만 반드시 상수에만 사용하는 것은 아닙니다. 특징은 앞서 살펴본 let과 동일하며 블록 레벨 스코프로 동작한다.

 

const는 다음과 같이 선언과 동시에 할당이 이루어져야 하고 재할당이 금지된다.

const CONST_VAL;  // SyntaxError

const CONST_VAL = 123;
CONST_VAL = 456;  // TypeError

 

const와 객체

const로 선언한 변수에는 객체도 할당하여 사용할 수 있지만 재할당은 금지된다. 따라서 const로 선언한 객체 타입의 변수에 할당된 객체의 주소값은 변경되지 않는다.

 

또한 객체의 재할당은 불가능하지만 객체의 프로퍼티는 변경이 가능하다. 이러한 특징으로 인해 객체 타입의 변수를 선언할 때는 const를 사용하는 것이 좋다.

const object = {
    name: 'harry'
};

object.name = 'kim';
console.log(object.name);   // kim

// TypeError
object = {
    name: 'john'
};

 


원 출처는 https://freestrokes.tistory.com/101 입니다.

반응형

'FrontEnd > JavaScript' 카테고리의 다른 글

로컬 스토리지(Local Storage)  (0) 2021.04.20
<script>를 <body> 맨 뒤에 삽입하는 이유?  (0) 2021.04.19
바닐라 자바스크립트(Vanilla JS)란?  (0) 2021.04.19
AJAX 정리  (0) 2020.12.09
jQuery(제이쿼리) 정리  (0) 2020.12.09
Comments