비바라기's
[JS] 스코프와 호이스팅 본문
목차
1. 호이스팅(hoisting)이란
2. 호이스팅이 필요한 이유?
3. let 과 const를 구분하여 사용하기
호이스팅(hoisting)이란
전역 스코프와 지역 스코프
만약 어떤 변수가 함수 내부에 정의되었거나, 중괄호 밖에 정의되었다면 이 변수를 전역 스코프에 정의되었다고 말합니다. 반대로 중괄호 내부에 정의된 변수가 있다면 이 변수는 지역 스코프라고 합니다.
만약 어떤 지역 스코프에서 선언된 변수가 있다면, 이 변수는 전역 스코프나 다른 함수(즉 다른 지역 스코프)에서 참조할 수 없습니다.
var a = 1;
function test() {
var b = 2;
console.log(a); /* 1이 출력됩니다. */
console.log(b); /* 2가 출력됩니다. */
}
console.log(b); /* b는 지역 스코프 변수이므로 참조할 수 없습니다. ReferenceError: b is not defined */
호이스팅
호이스팅은 자바스크립트의 특징 중 하나로, 함수 안에서 변수를 선언하면 "어떤 위치에 있던" 그 함수의 시작 위치로 끌어올리는 현상입니다. 예시 코드와 함께 보시겠습니다. 1
function test(){
console.log(a) // 초기화 후 "hoist"라는 string이 할당되기 전이므로, undefined가 출력됩니다.
var a = "hoist"
console.log(a) // "hoist"라는 string이 출력됩니다.
}
test()
변수 뿐만 아니라 함수도 호이스팅됩니다.
test()
function test(){
console.log("hello world!")
}
// 위의 코드와 아래의 코드는 동일한 결과물을 출력합니다.
function test(){
console.log("hello world!")
}
test()
변수의 a의 선언 이전에 console.log를 통해 a를 호출하는 것이 가능한 이유는 자바스크립트가 변수 a에 "hoist"라는 string을 할당하기 전에 1. 변수 a를 선언하고, 2. 데이터를 할당한 뒤, 3. 변수를 초기화하기 때문입니다. 이 과정은 자바스크립트 코드가 실제로 실행되기 전, 실행 컨텍스트 과정에서 먼저 수행됩니다. 실행 컨텍스트에 대해서는 후술하겠습니다.
즉 위의 코드는 형식적으로 다음의 코드와 같습니다.
function test(){
var a // 변수 a를 선언하고, 데이터 공간을 할당한 뒤, 초기화합니다.
console.log(a) // 초기화된 a의 값을 호출합니다(= undefined).
var a = "hoist"
console.log(a) // "hoist"가 return됩니다.
}
test()
호이스팅이 필요한 이유
C와 자바스크립트의 공통점 중 하나는 둘 다 호이스팅(hoisting)을 통해 변수를 선언하고 초기화한다는 점 입니다. 지금에는 주로 JS에서 변수를 '잘' 선언하는 방법과 관련하여 호이스팅 개념이 다루어지지만, 호이스팅은 초기 JS만을 위한 고유한 아이디어가 아니었으며, 당대 개발자들이 공유하던 어떤 패러다임의 하나로 볼 수 있을 것 같습니다.
자바스크립트는 코드를 실행하기 위해 일종의 전처리 과정을 거칩니다. 이 전처리 과정을 실행 컨텍스트 과정이라고 부릅니다. 자바스크립트는 전처리 과정에서 미리 코드 내부의 변수들과 함수들을 파악합니다. 그리고 그 변수들과 함수들을 위한 메모리 공간을 할당하고, 초기화하는 과정을 거칩니다. 이 과정을 파싱(Parsing)이라고 합니다 2. 변수들과 함수들은 자신의 직접 상위 객체의 멤버로 포섭됩니다(스코프 등록). 파싱은 전역 수준에서 먼저 일어나고, 전역 수준의 파싱이 끝난 뒤 코드가 실행 단계로 들어서면, 자바스크립트는 함수를 만날 때마다 다시 그 함수의 지역 수준에서 파싱 과정을 거칩니다. 3
파싱 과정에서 자바스크립트 전역/ 지역 스코프의 첫 시작점 수준으로 변수등을 끌어올리는(hoisting)것과 같은 현상은 자바스크립트에게 미리 이러이러한 변수들과 함수들을 쓸 것이라고 알려주는 역할을 할 수 있습니다. 하지만 실행 컨텍스트 과정에서 초기화된 변수가 코드의 실행 단계에서 개발자가 의도한 값이 할당되기도 전에 호출됨으로써 예기치 못한 오류를 발생시킬 수 있습니다.
이런 문제때문에 ES2015 이후부터 자바스크립트에서 var 대신 let과 const를 사용할 수 있게 됩니다. let과 const는 실행 컨텍스트 과정에서 호이스팅이 발생하는 것은 동일하지만, var와 달리 선언만 가능하고 데이터 할당과 초기화가 이루어지지 않음으로써, 개발자가 의도한 값이 할당되기 전, 미리 참조할 수 없게 만들어졌습니다.
function test(){
console.log(a) // let으로 선언한 a는 아직 초기화되지 않았으므로, 참조할 수 없습니다.
//ReferenceError: Cannot access 'a' before initialization
let a = 1 // const로 선언하였더라도 마찬가지입니다.
console.log(a)
}
test()
또한 let과 const는, 함수 스코프를 가진 var와는 달리 블록 스코프를 가지고 있습니다. 때문에 중괄호( { ... } ) 내부에서 let과 const를 통해 선언된 변수를 중괄호 밖에서는 재정의할 수 없는 반면, function scope인 var를 통해 선언한 경우는 그렇지 않습니다.
아래는 함수 스코프인 var를 통해 변수 a를 선언한 코드입니다.
function test(){
var a = 1
function test2(){
var a = 2 // 함수 test2 안에서 var로 변수 a를 다시 선언하였습니다.
}
console.log(a) // 1이 출력됩니다.
test2() // 함수 test2 안에서 var로 선언된 함수 a는 함수 밖에서는 사용될 수 없습니다.
console.log(a) // 따라서 처음과 같이 1이 출력됩니다.
}
test()
다만 function도 중괄호로 감싸진 하나의 블럭이기 때문에, 함수 스코프인 var 대신 블럭 스코프인 let으로 변수 a를 재선언해도 같은 결과가 나올 것입니다. 때문에 이번에는 함수가 아니면서 중괄호를 사용하는 for 반복문을 사용해보겠습니다.
function test(){
for(let a= 1; a< 5; a++){
console.log(a) // 1, 2, 3, 4를 출력합니다.
}
console.log(a) // for문의 중괄호 밖에서 let a는 참조할 수 없습니다.
// ReferenceError: a is not defined
}
test()
let 과 const 를 구분하여 사용하기
let으로 선언한 변수는 재선언이 불가능하지만 변수에 재할당하는 것은 가능합니다. 하지만 const는 변수를 재선언하거나, 재할당할 수 없습니다.
let a = 1
console.log(a) // 1이 출력됩니다.
let a = 2
console.log(a) // let은 재선언이 불가능합니다.
// SyntaxError: Identifier 'a' has already been declared
a = 3 // let은 재할당이 가능합니다.
console.log(a) // 1이 출력됩니다.
const a = 1
console.log(a) // 1이 출력됩니다.
const a = 2
console.log(a) // const는 재선언이 불가능합니다.
// SyntaxError: Identifier 'a' has already been declared
const = 3
console.log(a) // const는 재할당도 불가능합니다.
// SyntaxError: Unexpected token '='
- https://edu.goorm.io/learn/lecture/557/%ED%95%9C-%EB%88%88%EC%97%90-%EB%81%9D%EB%82%B4%EB%8A%94-node-js/lesson/226443/%EC%8A%A4%EC%BD%94%ED%94%84%EC%99%80-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85 [본문으로]
- https://hanamon.kr/javascript-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85%EC%9D%B4%EB%9E%80-hoisting/ [본문으로]
- https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=krquddnr37&logNo=220322360057 [본문으로]
'TIL > 웹개발 종합반' 카테고리의 다른 글
[CSS] 구글 폰트 / 부트스트랩 5.0 시작 템플릿(카피&페이스트) (0) | 2022.08.17 |
---|---|
자주 쓰이는 HTML & CSS 태그 사전 링크 (0) | 2022.08.16 |
[HTML, CSS] 메타 태그란? & 선택자란? (0) | 2022.08.14 |
HTML, CSS란 ? (0) | 2022.08.14 |