💁♀️ 스코프(Scope)란,
변수에 접근할 수 있는 범위
💁♀️ 전역 스코프란,
코드의 가장 바깥 영역을 의미하며, 전역에 변수를 선언하면 전역 스코프를 갖는 전역 변수가 되고 전역 변수는 어디서든 참조 가능
💁♀️ 지역 스코프란,
함수 내부 영역을 의미하며, 지역에 변수를 선언하면 지역 스코프를 갖는 지역 변수가 되고 자신의 지역 스코프와 하위 지역 스코프에서만 유효
var x = 'global x';
var y = 'global y';
function outer() {
var z = "outer's local z";
console.log(x); // global x
console.log(y); // global y
console.log(z); // outer's local z
function inner() {
var x = "inner's local x";
console.log(x); // inner's local x
console.log(y); // global y
console.log(z); // outer's local z
}
inner();
}
outer();
console.log(x); // global x
console.log(y); // global y
console.log(z); // ReferenceError: z is not defined
📌 Ref.
* 스코프 체인
- 전역 스코프 (x, y, outer) 👈 outer 지역 스코프 (z, inner) 👈 inner 지역 스코프 (x)
- 자바스크립트 엔진은 변수를 참조할 때 스코프 체인을 통해 변수를 참조하는 코드의 스코프에서 시작하여 상위 스코프 방향으로 이동하며 선언된 변수를 검색
=> 상위 스코프에서 유효한 변수는 하위 스코프에서 자유롭게 참조 가능,
하위 스코프에서 유효한 변수는 상위 스코프에서 참조 불가능
💁♀️ C, Java 등 대부분의 프로그래밍 언어는 함수 몸체만이 아니라 모든 코드 블록(if, for, while, try/catch 등)이 지역 스코프를 만드는 "블록 레벨 스코프"를 가짐
💁 var 키워드로 선언된 변수는 오로지 함수의 코드 블록만을 지역 스코프로 인정하는 "함수 레벨 스코프"를 가짐
// i는 전역변수
var i = 0;
// 전역변수로 이미 선언된 i가 중복 선언
for(var i = 0; i < 10; i++) {}
// for 코드 블럭 내부의 값 변화가 반영
console.log(i); // 0이 아닌 10 출력
=> var 변수의 문제(함수 레벨 스코프를 가지기 때문에 의도하지 않은 결과가 출력)
var msg = '안녕!';
console.log(msg);
// var 키워드로 선언된 변수는 같은 스코프 내에서 중복 선언이 허용
// 초기화 문이 있는 변수 선언문은 자바스크립트 엔진에 의해 var 키워드가 없는 것처럼 동작
var msg = '잘가!';
console.log(msg);
// 초기화 문이 없는 변수 선언문은 무시
var msg;
console.log(msg); // 잘가! 출력
// 함수 외부에서 var 키워드로 선언한 변수는 코드 블록 내에서 선언해도 모두 전역 변수
var i = 0;
for(var i = 0; i < 10; i++) {}
console.log(i); // 10 출력 (블럭 레벨에서는 스코프를 나누지 않음)
// 변수 선언문이 스코프의 선두로 끌어 올려진 것 처럼 동작
// 변수 선언문 이전에 참조
console.log(test); // undefined
test = '반가워요!'
console.log(test); // 선언문이 아래에 있음에도 불구하고, '반가워요!'가 정상 출력 (호이스팅)
var test;
💁 var 키워드의 단점을 보완하기 위해 ES6 에서는 새로운 변수 선언 키워드인 let, const를 도입
let msg = '안녕하심까';
// 같은 스코프 내에서 중복 선언 허용 X
// let msg = '안녕히가십쇼';
// 모든 코드 블록을 지역 스코프로 인정
let i = 0;
for(let i = 0; i < 5; i++) {
console.log(`지역 변수 i : ${i}`);
}
console.log(`전역 변수 i : ${i}`);
// 변수 호이스팅이 발생하지 않은 것처럼 동작
console.log(x); // ReferenceError: Cannot access 'x' before initialization
let x;
📌 Ref.
* var - 선언, 초기화 동시
* let - 선언, 초기화 분리되어 동작
💁 let 키워드에서 알아본 특징과 모두 동일하며, 상수(const) 선언에서 사용된다는 점이 또 다른 특징
// const x;
const x = 1;
// x = 2; // TypeError: Assignment to constant variable
const DISCOUNT_RATE = 0.15;
const student = {
name : '강호둥',
age : 20
};
student.name = '유재성';
console.log(student);
// student = {}; // TypeError: Assignment to constant variable.