본문 바로가기
Javascript

Javascript 변수(Variables)

by Redking

Javascript에서 새로운 변수를 선언할 때 var, let, const 키워드가 사용 가능합니다. 변수는 애플리케이션에서 한번 쓰고 버리는 값이 아닌 일정 기간 유지할 필요가 있는 값에 사용하며 변수를 사용하면 값의 의미가 명확해져 코드 가독성 증가에 도움이 됩니다.

 

변수명을 지정할때 변수의 존재 목적에 알맞은 변수명을 지정해야 이후 유지보수 시 도움이 됩니다.

var abc = '2025-01-22';    // bad case
var today = '2025-01-22';  // good case

 

변수명은 식별자(identifier)로 불리기도 하며 명명 규칙이 존재한다.

  • 반드시 영문자(특수문자 제외), underscore ( _ ), 또는 달러 기호($)로 시작하여야 한다. 이어지는 문자에는 숫자(0~9)도 사용할 수 있다.
  • 자바스크립트는 대/소문자를 구별하므로 사용할 수 있는 문자는 “A” ~ “Z” (대문자)와 “a” ~ “z” (소문자)이다.

 

값을 할당하지 않은 변수 즉 선언만 되어 있는 변수는 undefined로 초기값을 갖는다. 선언하지 않은 변수에 접근하면 ReferenceError가 발생한다.

var x;
console.log(x); // undefined
console.log(y); // ReferenceError

자바스크립트의 변수는 다른 C-family와는 달리 블록 레벨 스코프(block-level scope)를 가지지 않고 함수 레벨 스코프(function-level scope)를 갖는다. 단, ECMAScript 6에서 도입된 let, const 키워드를 사용하면 블록 레벨 스코프를 사용할 수 있다.

함수 레벨 스코프(Function-level scope)

함수 내에서 선언된 변수는 함수 내에서만 유효하며 함수 외부에서는 참조할 수 없다. 즉, 함수 내부에서 선언한 변수는 지역 변수이며 함수 외부에서 선언한 변수는 모두 전역 변수이다.

블록 레벨 스코프(Block-level scope)

코드 블록 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다.


var

변수를 선언하고 선택적으로 초기화 할 수 있습니다. 어디에 선언이 되어있든 변수들은 코드가 실행되기 전에 처리가 됩니다. var로 선언된 변수의 범위는 현재 실행 문맥인데, 그 문맥은 둘러싼 함수, 혹은 함수의 외부에 전역으로 선언된 변수일 수도 있습니다.

var x = 0;  // x는 전역으로 선언되었고, 0으로 할당됩니다.

console.log(typeof z); // undefined, z는 아직 존재하지 않습니다.

function a() { // a 함수를 호출했을 때,
  var y = 2;   // y는 함수 a에서 지역변수로 선언되었으며, 2로 할당됩니다.

  console.log(x, y);   // 0 2

  function b() {       // b 함수를 호출하였을때,
    x = 3;  // 존재하는 전역 x값에 3을 할당, 새로운 전역 var 변수를 만들지 않습니다.
    y = 4;  // 존재하는 외부 y값에 4를 할당, 새로운 전역 var 변수를 만들지 않습니다.
    z = 5;  // 새로운 전역 z 변수를 생성하고 5를 할당 합니다.
  }         // (strict mode에서는 ReferenceError를 출력합니다.)

  b();     // 호출되는 b는 전역 변수로 z를 생성합니다.
  console.log(x, y, z);  // 3 4 5
}

a();                   // 호출되는 a는 또한 b를 호출합니다.
console.log(x, z);     // 3 5
console.log(typeof y); // undefined y는 function a에서 지역 변수입니다.

var 키워드로 선언한 변수는 중복 선언이 가능합니다.

var x = 1;
console.log(x);  // 1

var x = 3;
console.log(x);  // 3

변수 호이스팅이란 var 선언문이나 function 선언문 등 모든 선언문이 해당 Scope의 선두로 옮겨진 것처럼 동작하는 특성을 말한다. 즉, 자바스크립트는 모든 선언문(var, let, const, function, function*, class)이 선언되기 이전에 참조 가능하다.

console.log(foo); // ① undefined
var foo = 123;
console.log(foo); // ② 123
{
  var foo = 456;
}
console.log(foo); // ③ 456

 

var 키워드로 선언된 변수는 선언 단계와 초기화 단계가 한 번에 이루어진다.

즉, 스코프에 변수가 등록되고 변수는 메모리에 공간을 확보한 후 undefined로 초기화된다. 따라서 변수 선언문 이전에 변수에 접근하여도 Variable Object에 변수가 존재하기 때문에 에러가 발생하지 않는다. 다만 undefined를 반환한다. 이러한 현상을 변수 호이스팅(Variable Hoisting)이라한다.

 

var 키워드로 선언된 변수의 문제점

  1. 함수 레벨 스코프
    • 전역 변수의 남발
    • for loop 초기화식에서 사용한 변수를 for loop 외부 또는 전역에서 참조할 수 있다.
  2. var 키워드 생략 허용
    • 의도하지 않은 변수의 전역화
  3. 중복 선언 허용
    • 의도하지 않은 변숫값 변경
  4. 변수 호이스팅
    • 변수를 선언하기 전에 참조가 가능하다.

let

블록 유효 범위를 갖는 지역 변수를 선언하며, 선언과 동시에 임의의 값으로 초기화할 수도 있다.

var이 아니라 let을 사용하는 이유는 앞서 언급한 var의 4가지 문제점 때문이다. var 은 함수 레벨 스코프였던 반면, let 은 블록 레벨 스코프 변수를 선언한다. 또한 letlet으로 변수 이름을 중복하여 선언할 수 없으며 SyntaxError문법 에러가 발생한다.

let x = 1;

if (x === 1) {
  let x = 2;

  console.log(x);
  // expected output: 2
}

console.log(x);
// expected output: 1

if (x) {
  let foo;
  let foo; // SyntaxError thrown.
}

 

전역 객체란 모든 객체의 최상위 객체로 브라우저에서 window 객체가 그 예시이다. var 키워드로 선언된 변수는 전역 객체의 프로퍼티가 된다. 그러나 letlet으로 선언한 전역 변수는 전역 객체의 프로퍼티가 될 수 없다.

var a = 10;
let b = 5;
console.log(window.a) // 10
console.log(window.b) // undefined

 

let은 var과 다르게 호이스팅이 되지 않는다.

function do_something() {
  console.log(bar); // undefined
  console.log(foo); // ReferenceError
  var bar = 1;
  let foo = 2;
}

 

switch를 사용할 때는 실제 블록이 하나뿐이므로 중복 선언 오류가 발생하기 쉽습니다.

let x = 1;
switch(x) {
    case 0:
        let foo;
        break;
    case 1:
    	let foo;  // SyntaxError
        break;
}

하지만 case 조건을 새로운 블록으로 감싸면 위의 코드와는 다르게 재선 언 오류가 발생하지 않습니다.

let x = 1;

switch(x) {
    case 0: {
    	let foo;
    	break;
	}
    case 1: {
    	let foo;
    	break;
  	}
}

 

블록을 사용할 때, let은 변수의 유효 범위를 블록으로 제한합니다. 함수 내 또는 전역을 유효 범위로 가지는 var와의 차이점입니다.

var a = 1,
	b = 2;
    
if (a === 1) {
	var a = 3;  // 전역 변수
    let b = 4;  // if 블록 내에서만 유효한 변수
    console.log(a);  // 3
    console.log(b);  // 4
}
console.log(a);  // 3
console.log(b);  // 2

const

const 선언은 블록 범위의 상수를 선언합니다. const의 값은 재할당할 수 없으며 다시 선언할 수도 없습니다. 이 선언은 const 초기값이 필요합니다. 즉 선언과 동시에 그 값을 지정해야 하며 이는 나중에 변경될 수 없는 점을 고려하면 당연합니다. const는 같은 범위의 const 또는 변수와 이름을 공유할 수 없습니다.

 

const 선언에는 대소문자 모두 사용할 수 있지만, 일반적인 관습은 모두 대문자를 사용하는 것입니다.

const MY_FAV = 7;

MY_FAV = 20;  // Uncaught TypeError: Assignment to constant variable.

console.log("my favorite number is: " + MY_FAV);  // my favorite number is: 7

const MY_FAV = 20;  // Uncaught SyntaxError: Identifier 'MY_FAV' has already been declared


var MY_FAV = 20;  // Uncaught SyntaxError: Identifier 'MY_FAV' has already been declared

// 역시 오류가 발생함
let MY_FAV = 20; // Uncaught SyntaxError: Identifier 'MY_FAV' has already been declared


// 블록 범위의 특성을 아는게 중요
if (MY_FAV === 7) {
    // 블록 범위로 지정된 MY_FAV 라는 변수를 만드므로 괜찮습니다
    // (let으로 const 변수가 아닌 블록 범위를 선언하는 것과 똑같이 동작합니다)
    let MY_FAV = 20;

    console.log('my favorite number is ' + MY_FAV);  // my favorite number is: 20

    var MY_FAV = 20;  // 이 선언은 전역으로 호이스트되고 에러가 발생합니다.
}

console.log('my favorite number is ' + MY_FAV);  // my favorite number is: 7

// const 선언시에 초기값을 생략해서 오류 발생
const FOO;

// const는 오브젝트에도 잘 동작합니다
const MY_OBJECT = {'key': 'value'};

// 오브젝트를 덮어쓰면 오류가 발생합니다
MY_OBJECT = {'OTHER_KEY': 'value'};

 

'Javascript' 카테고리의 다른 글

JavaScript 화살표 함수  (0) 2021.03.30
JavaScript 타입별 정리 Undefined  (0) 2021.03.24
JavaScript 타입별 정리 Object (2)  (0) 2021.03.23
JavaScript 예약어 모음  (0) 2021.03.23
JavaScript 타입별 정리 Object (1)  (0) 2021.03.23

댓글