2023년 3월 16일 목요일

변수 선언 : let, const

 

변수 선언 : let, const

변수 선언과 초기화

JavaScript에서 변수를 선언할 때 var를 많이 사용해 왔었는데, var를 통해서 변수를 선언하고 나중에 값을 초기화하거나, var 변수를 선언과 동시에 값을 할당하기도 한다. JavaScript에서 선언된 모든 변수는 별도로 초기화되지 않는 한 디폴트로 undefined 값을 갖는다.

1
2
3
4
5
6
7
8
9
10
11
// 변수 선언
var a;
console.log(a); // "undefined" 출력
 
// 변수 초기화
a = "Hello";
console.log(a); // "Hello" 출력
 
// 변수 선언과 초기화
var b = 123;
console.log(b); // 123 출력
let vs var

JavaScript에서 변수를 선언할 때 (ECMAScript 6 이전까지) var를 사용하였는데, var 변수가 함수 안에 있으면 로컬 변수로서 그 함수 혹은 내부 중첩함수(nested function) 안에서만 사용되며 (function scoped), var 변수가 함수 밖에 있으면 전역 변수로서 스크립트 전체에서(global scoped) 사용가능하다.

아래 예제에서 함수 안에서 정의된 sum, i, sq 등은 함수 내에서만 사용할 수 있는 Function Scope의 로컬 변수이다. 그리고, 함수 밖에 정의된 var result는 Global Scope의 전역 변수이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function squareSum(scores) {
    // 로컬변수 (function scoped)
    var sum = 0;
 
    console.log(sq); // "undefined" 출력
 
    for (var i = 0; i < scores.length; i++) {
        var sq = scores[i] * scores[i];
        sum += sq;
    }
 
    console.log(sq); // 9 출력
 
    return sum;
}
 
// result: 전역변수 (global scoped)
var result = squareSum([1,2,3]);
console.log(result);

함수 안에 있는 sum, i, sq 는 모두 다른 위치에서 var 변수로 선언되었는데, JavaScript에서 이들 var 변수들은 변수 생성과정에서 함수 처음부분에 모두 디폴트 값인 undefined를 갖는다. 즉, var sq 가 for 루프 안에서 정의되었다고 하더라도, sq는 함수 첫부분에 이미 undefined로 초기화 된다는 것이다. 이러한 이유때문에 for 루프 앞에서 (var sq가 선언되기 이전에) sq를 콘솔 출력해 보면 "undefined" 출력되게 된다. 다시 말하면, var로 선언된 sum, i, sq 변수 모두는 함수 범위에서 처음부터 사용할 수 있는 것이다. 타 언어와 비교하면, 이러한 특징은 때로 혼란을 야기하고 예기치 못한 버그를 발생시키곤 한다. 이러한 문제점을 해결하고자 ECMAScript 6 (ES6 / ES2015)에서 let과 const를 도입하였는데, 이들은 모두 타 언어와 비슷하게 블럭 안에서 변수가 생성/소멸되는 특징(Block scoped)을 갖는다.

아래 예제는 위 함수에서 sq 변수를 var 대신 let 으로 정의한 것으로, 이렇게 let으로 변수를 정의하면 sq의 변수 범위가 for 루프 안으로 좁혀 지게 된다. 따라서, for 루프 위나 아래에서 console.log(sq) 을 사용하게 되면, 해당 변수가 범위를 벗어나므로 ReferenceError 에러를 발생시킨다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function squareSum(scores) {
    let sum = 0;
 
    // 에러 "ReferenceError: sq is not defined"
    //console.log(sq);
 
    for (let i = 0; i < scores.length; i++) {
        let sq = scores[i] * scores[i];
        sum += sq;
    }
 
    // 에러 "ReferenceError: sq is not defined"
    console.log(sq);
 
    return sum;
}

TypeScript에서는 통상 모든 구문에서 var 대신 let 혹은 const를 사용하여 보다 명료하게 변수 범위를 설정하도록 한다.

let vs const

let과 const는 블럭 범위를 갖는다는 점에서 동일하지만, let은 여러 번 값을 재할당할 수 있지만, const는 일단 한번 값이 할당되면 다시 값을 할당할 수 없다는 차이점이 있다. 즉, var는 함수 범위(function scope)의 변수를 선언하는 것이고, let과 const는 블럭 단위의 범위(block scope)의 변수를 선언하는 것인데, const는 let과 달리 한번 값이 할당되면 다시 값을 할당할 수 없다는 차이가 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 상수 정의
const PI = 3.14;
 
// person 변수는 재할당 못함
const person = {
    id: 1,
    name: "Tom"
}
 
// 에러 "Cannot assign to 'person' because it is a constant"
// person = { id: 2 }
 
// 정상 : person은 변하지 않았음
person.name = "Jerry";
console.log(person); // { id: 1, name: 'Jerry' } 출력

위 예제에서 PI는 상수로 정의되었다. 두번째 person 역시 상수로 정의되었는데, 이 경우는 person이 객체로서 person = {id:2} 와 같이 person에 새로운 객체를 할당할 수는 없지만, person.name = "Jerry"와 같이 객체 내에 있는 속성을 변경할 수 있다.

댓글 없음:

댓글 쓰기