scope와 var, const, let
1. 스코프(scope) : 유효범위
변수가 선언되고 나면 그 변수를 사용할 수 있는 범위가 정해져있다. 예를 들어, 함수 내부에서 선언된 변수는 함수 내부에서만 사용할 수 있고 가장 바깥에서 실행된 변수는 어디서든 사용할 수 있다. 이렇게 변수를 참조할 수 있는 유효한 범위를 스코프라고 한다.
1.1 전역 스코프
const text = "hello";
console.log(text); // hello
코드의 가장 바깥, 즉 전역에서 선언한 변수는 어디서든 참조할 수 있다.
1.2 함수 스코프
const text = "hello";
function add(){
const a = 0;
const b = 1;
return a + b;
};
console.log(a); // Uncaught ReferenceError: a is not defined
console.log(text); // hello
함수 내부에서 선언한 변수는 함수 안에서만 사용할 수 있다. 함수 외부에서 사용하면 참조 에러가 발생한다.
1.3 블럭 스코프
for(let i = 0; i < 3; i++){
let num = 0;
num = num + i;
};
console.log(num); // Uncaught ReferenceError: num is not defined
블럭 안에서 선언한 변수는 블럭 안에서만 사용할 수 있다. 블럭 외부에서 사용하면 참조 에러가 발생한다.
2. 렉시컬 스코프
const x = 1;
function a() {
const x = 2;
console.log(x);
};
a(); // 2
함수가 사용될 때, 함수를 어디서 호출했는지가 아닌, 함수가 어디서 선언되었는가를 기준으로 스코프가 결정되는 것이다. const x = 1은 전역으로, const x = 2는 함수 내부에서 사용되었지만 a()를 호출했을 때 x = 2라는 값이 출력된다. x라는 값이 함수의 호출 위치가 아닌 선언 위치를 기준으로 값이 결정되었기 때문이다.
3. 변수
변수는 var, let, const로 선언할 수 있다.
3.1 var
var로 변수 선언 및 값의 재할당이 가능하다.
var num = 1;
console.log(num); // 1
num = 2;
console.log(num); // 2
그러나 var는 3가지 문제가 있다.
console.log(text); // undefined
text = "hello";
var text;
첫번째, var는 호이스팅 된다. var로 코드를 이렇게 작성해도 에러가 나지 않는다. 변수를 선언하기도 전에 값을 할당하는 게 가능하고, 할당 이전에 사용도 가능하다. 값을 할당하기 전에 사용하면 결과값은 undefined로 나오지만 에러가 나오지는 않는다. 이처럼 var는 변수를 어디서 선언하든, var로 선언한 변수는 호이스팅 되어서 어디에서든 사용할 수 있다.
for(var i = 0; i < 7; i ++){
i = i + 1;
};
console.log(i); // 8
두번째, var는 블럭 스코프를 지원하지 않는다. 즉, 블럭 안에서 선언된 변수를 밖에서도 사용할 수 있다.
var num = 1;
console.log(num); // 1
var num = 2;
console.log(num); // 2
세번째, var은 같은 이름으로 다시 변수를 선언할 수 있다. 이러한 var의 특징은 개발 중 큰 문제를 만들 수 있기 때문에 ES6부터는 var의 문제를 해결한 let과 const를 사용한다.
3.2 let
ES6부터는 var 대신 let을 사용한다. let은 블럭 스코프를 지원하기 때문에 var과 달리 아무 곳에서나 사용할 수 없다.
console.log(text); // Uncaught ReferenceError: text is not defined
text = "hello";
let text;
let은 값을 재할당할 수 있다. 그러나 같은 이름의 변수를 다시 선언하는 것은 불가능하다.
let num;
num = 1;
console.log(num); // 1
num = 2;
console.log(num); // 2
let num = 3; // Uncaught SyntaxError: Identifier 'num' has already been declared
3.3 const
변수 중에서도 값을 변경하지 않는 변수는 const로 선언하는 것이 좋다. const도 블럭 스코프를 지원한다.
const num = 1;
console.log(num); // 1
num = 2; // Uncaught TypeError: Assignment to constant variable.
const로 선언된 변수는 값을 변경할 수 없다. 개발 과정에서 값이 변경될 일이 없는 변수는 const로 선언하고, 그 이외의 변수는 let으로 선언해주는 것이 좋다.
const name; // Uncaught SyntaxError: Missing initializer in const declaration
const로 변수를 선언할 때는 선언과 동시에 값을 할당해야 한다.
참고 자료
모던 자바스크립트 Deep Dive 13장
드림코딩님 https://youtu.be/OCCpGh4ujb8
얄팍한 코딩 사전님 https://youtu.be/HsJ4oy_jBx0
'FE > JavaScript' 카테고리의 다른 글
[JavaScript] 메모리와 값의 복사 (0) | 2022.10.27 |
---|---|
[JavaScript] 구조분해할당 (0) | 2022.10.26 |
[JavaScript] callback 함수 (0) | 2022.10.24 |
[JavaScript] 데이터 타입과 타입 변환 (0) | 2022.10.23 |
[JavaScript] 함수 선언문과 함수 표현식 (0) | 2022.10.23 |