다음 세가지 항목은 변수 선언 키워드라고 불리우며,
이 키워드를 통해 변수와, 상수를 선언할 수 있습니다.
ES6 버전 이후 var 키워드 사용은 권장하지 않고 있으므로 let과 const를 활용한 변수 선언 방식을 권장합니다.
var (권장x) | let (변수) | const (상수) | |
---|---|---|---|
값 재선언 | ○ | Χ | Χ |
값 재할당 | ○ | ○ | Χ |
스코프 (scope) | Function level | ||
함수레벨 스코프 | Block({}) level | ||
블록레벨 스코프 | Block({}) Scope | ||
블록레벨 스코프 | |||
호이스팅 (hoisting) | ○ | △ | |
Temporal Dead Zone | △ | ||
Temporal Dead Zone |
//================================ 값 재선언 / 재할당
var a = 2;
var a = 3; // 3 재선언
a = 5; // 5 재할당
let b = "old";
let b = "new"; // SyntaxError! Identifier "b" has already been declared 재선언 불가능
b = "old friend" // "old friend" 재할당 가능
const c = "java"
const c = "javascript" // SyntaxError! Identifier "c" has already been declared. 재선언 불가능
c = "python" // TypeError! Assignment to constant variable. 재할당 불가능
변수에 접근할 수 있는 범위를 가리킵니다.
범위는 중괄호(블록) 또는 함수에 의해 나누어집니다.
[주요 규칙]
1. 스코프 내부에서 외부로 접근할 수 있지만, 반대는 불가능합니다. (핵심)
- 스코프 외부에서 선언한 변수는 스코프 내부에서 사용할 수 있습니다.
- 스코프 내부에서 선언한 변수는 외부에서 사용할 수 없습니다.
2. 전역 스코프와 지역 스코프
- 전역 스코프 (Global Scope) 가장 바깥쪽의 스코프
- 지역 스코프 (Local Scope) 전역이 아닌 다른 스코프
3. 전역 변수와 지역 변수
- 전역 변수 전역 스코프에서 선언한 변수
- 지역 변수 지역 스코프에서 선언한 변수
- 지역 변수는 전역 변수보다 더 높은 우선 순위를 가집니다.
const div = document.querySelector(".box");
function 함수() {
const 상수 = "변하지 않아요"
console.log(상수)
console.log(div)
}
함수()
console.log(상수)
//스코프
//================================ 함수 스코프 ================================
// 함수 내부에서 선언된 스코프는 해당 함수 내에서만 선언할 수 있음.
// 함수의 중괄호 역시 블록스코프이기 때문에 let과 const는 함수 블록 내부 참조 불가
var outVar = "outer--var"
let outLet = "outer--let"
const outConst = "outer--const"
function a() {
console.log(outVar, outLet, outConst); // "outer--var", "outer--let", "outer--const"
var innerVar = "inner-var"
let innerLet = "inner-ler"
const innerConst = "inner-const"
console.log(innerVar, innerLet, innerConst) // "inner-var" "inner-ler" "inner-const"
// var 블록 스코프의 영향을 받지 않는다.
for ( var i = 0; i < 5 ; i++ ) {
console.log(i) // 0, 1, 2, 3, 4
}
console.log(i) // 5
}
a() // "outer--var", "outer--let", "outer--const"
// "inner-var" "inner-ler" "inner-const"
// 0 1 2 3 4
// 5
console.log(outVar, outLet, outConst); // "outer--var", "outer--let", "outer--const"
console.log(innerVar, innerLet, innerConst); // ReferenceError: innerVariable is not defined
//================================ 블록 스코프 ================================
// 대표적인 블록스코프 예시
// let (const 사용 시 TypeError: Assignment to constant variable 에러 발생)
for ( let i = 0; i < 5 ; i++ ) {
console.log(i) // 0, 1, 2, 3, 4
}
console.log(i) //ReferenceError: i is not defined
{
var blockVar = "block--var"
const blockConst = "block--const"
let blockLet = "block--let"
console.log(blockVar, blockConst, blockLet) // "block--var" "block--const" "block--let"
}
console.log(blockVar); // "block--var"
console.log(blockConst); // ReferenceError: blockConst is not defined
console.log(blockLet); // ReferenceError: blockLet is not defined
MDN : 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 가리킵니다.
쉬운 말
아래에 있는 선언(let, const , function, class)을
해당 스코프의 최상단으로 끌어올린다!
function 함수() {
console.log("클릭")
}
버튼.addEventListener("click", 함수);
// 호이스팅
//================================ 함수 먼저 ================================
function Hello() {
console.log("안녕하세요")
}
Hello() // "안녕하세요"
//================================ 선언 먼저 ================================
Hello() // "안녕하세요"
function Hello() {
console.log("안녕하세요")
}
// ================================ var ================================
// var*로 선언된 변수는 최상단으로 위치하게 되어 해당 코드가 정상적으로 실행된다.
var a = undefined // 선언 및 초기화 단계
console.log(a) // undefined
var a = 1
console.log(a) // 1*
// ================================ *let & const*================================
*// let과 const도 hoisting이 발생하지만 변수를 참조하기 위해서는
// 변수 선언한 부분을 넘어서야 된다. 그 이전까지를 일시적 사각지대라고 부른다.
console.log(b) // ReferenceError: Cannot access 'b' before initialization (TDZ ↑)
let b // 선언 단계
console.log(b) // undefined
let b = 2 // 변수에 값 할당을 통한 초기화
console.log(b) // 2*
Hoisting이 발생하는 코드는 가독성 낮아지고, 유지보수가 어려워집니다.
의도치 않은 결과물 출력 등의 결과를 맞이할 수 있어 Hoisting을 일부러 할 필요는 없지만 방지하는 것이 좋습니다.
Hoisting을 방지하기 위해 함수의 경우 선언 후에 호출을 하도록 하며, const와 let을 사용할 것을 권장합니다.
블록스코프 추가 이해
const
와 let
으로 선언한 값은 블록스코프로 선언이 되기 때문에 같은 블록 내에서 선언한 변수는 해당 블록 내에서만 사용이 가능합니다.
++ 블록 밖의 범위에서 똑같은 이름을 가진 값이 있다고 해도 영향을 주지 않습니다.
const value = '전역 스코프입니다!';
function functionScope() {
const value = '함수 스코프입니다!';
if (true) {
const value = '블록 스코프입니다!';
console.log('block scope: ');
console.log(value);
}
console.log('function scope: ');
console.log(value);
}
functionScope();
console.log('global scope: ');
console.log(value);