이번에 자바 스크립트의 Scope에 대해서 알아보자. Scope란 우리가 변수 혹은 함수를 선언하게 될 떄 해당 변수 또는 함수가 유효한 범위를 의미한다. Scope는 총 3가지 종류가 있다.
1. Global(전역) Scope: 코드의 모든 범위에서 사용이 가능
2. Function(함수) Scope: 함수 안에서만 사용이 가능하다.
3. Block(블록) Scope : if, for, switch등 특정 블록 내부에서만 사용이 가능하다.
예시를 통한 Scope이해
한번 예시 코드를 보고 Scope를 이해해 보자
const value = 'hello!';
function myFunction() {
console.log('myFunction: ');
console.log(value);
}
function otherFunction() {
console.log('otherFunction: ');
const value = 'bye!';
console.log(value);
}
myFunction();
otherFunction();
console.log('global scope: ');
console.log(value);
위 코드의 결과는 다음과 같다.

코드의 맨 윗줄에서 선언된 value값은 Global Scope로 선언된 값이다. Global Scope로 선언된 값은 어디서든지 사용이 가능하다. myFunction 에서 바로 사용을 할 수 있었다.
otherFunction에서는 함수 내부에서 value값을 'bye!'로 새로 선언을 해주었다. 이렇게 되면, value라는 값은 Function Scope로 지정이 되서 해당 값은 otherFunction 내부에서만 유효한 값이 된다. 이렇게 값을 설정한다고 해서 기존에 Global Scope로 선언된 value값이 바뀌지 않는다.
또 다른 예시를 확인해 보자.
const value = 'hello!';
function myFunction() {
const value = 'bye!';
const anotherValue = 'world';
function functionInside() {
console.log('functionInside: ');
console.log(value);
console.log(anotherValue);
}
functionInside();
}
myFunction()
console.log('global scope: ');
console.log(value);
console.log(anotherValue);

myFunction 내부에 anotherValue라는 새로운 값을 선언했고, functionInside라는 함수도 선언을 했다.
functionInside 함수에서는 myFunction에서 선언한 value값과 anotherValue 값을 조회 할수 있다.
반면, myFunction밖에서는 anotherValue를 조회 할 수 없다.
이제 또다른 예시를 알아보자.
const value = 'hello!';
function myFunction() {
const value = 'bye!';
if (true) {
const value = 'world';
console.log('block scope: ');
console.log(value);
}
console.log('function scope: ');
console.log(value);
}
myFunction();
console.log('global scope: ');
console.log(value);

const로 선언한 값은 Block Scope로 선언이 된다. 따라서 if 문 같은 블록 내에서 새로운 변수/상수를 선언하게 된다면, 해당 블록내부에서만 사용이 가능하고 블록밖의 범위에서 똑같은 이름을 가진 값이 있다고 해도 영향을 주지 않는다.
let또한 마찬가지 이다.
하지만 var는 어떨까?
var value = 'hello!';
function myFunction() {
var value = 'bye!';
if (true) {
var value = 'world';
console.log('block scope: ');
console.log(value);
}
console.log('function scope: ');
console.log(value);
}
myFunction();
console.log('global scope: ');
console.log(value);
var는 Function Scope로 선언이 되므로, if 문 블록 내부에서 선언한 value값이 블록 밖의 value에도 영향을 미치게 된다.

Hoisting 이해하기
Hoisting이란 자바스크립트에서 아직 선언되지 않은 함수/변수를 "끌어올려서" 사용 할수 있는 자바스크립트의 작동 방식을 의미한다.
다음코드를 확인해 보자.
myFunction();
function myFunction() {
console.log('hello world!');
}
위 코드에서는 myFunction함수를 선언하기 전에,
myFunction()을 호출해 주었다. 함수가 아직 선언되지않았음에도 불구하고 코드는 정상적으로 작동하게 된다.
이게 잘 작동하는 이유는, 자바스크립트 엔진이 위 코드를 해석하는 과정에서, 다음과 같이 받아 들이게 되기 때문이다
function myFunction() {
console.log('hello world!');
}
myFunction();
이러한 현상을, Hoisting이라고 부른다.
변수 또한 Hoisting 된다.
예를 들어서, 다음과 같은 코드를 실행한다면,
console.log(number);

이런 오류가 발생한다.
그렇지만, 다음과 같은 코드는
console.log(number);
var number = 2;

undefined가 출력된다.
자바스크립트 엔진이 위 코드를 해석 할 때는 다음과 같이 받아들이게 된다.
var number;
console.log(number);
number = 2;
반면 const와 let은 hoisting이 발생하지 않고, 에러가 발생하게 된다. Codesandbox에서는 자바스크립트가 Bable이라는 도구에 의하여 const와 let이 var로 변환되기 때문에 오류가 발생하지 않는다. Chrome 개발자 도구의 콘솔에서 다음 코드를 실행해 보자.
function fn() {
console.log(a);
let a = 2;
}
fn();

Hoisting은 자바스크립트 엔진이 갖고 있는 성질이며, Hoisting을 일부러 할 필요는 없지만, 방지하는 것이 좋다. 왜냐하면 Hoisting이 발생하는 코드는 이해하기 어렵기 때문에 유지보수도 힘들어지고 의도치 않는 결과물이 나타나기 쉽기 때문이다.
Hoisting을 방지하기 위해서, 함수의 경우 꼭 선언후에 호출을 하도록 주의를 하고, var대신 const,let을 위주로 사용하자. 추가적으로 나중에 자바스크립트 개발을 본격적으로 하게 될 때에는 EsLint 라는것을 사용하여 Hoisting이 발생하는 코드는 에디터상에서 쉽게 발견해 낼수 있다.
'공부내용정리 > JavaScript' 카테고리의 다른 글
| 카운터 (0) | 2021.04.28 |
|---|---|
| spread와 rest (0) | 2021.04.26 |
| 비구조화 할당 (구조분해) 문법 (0) | 2021.04.21 |
| 조건문 더 스마트 하게 쓰기 (0) | 2021.04.20 |
| 단축 평가(short-circuit evaluation)논리 계산법 (0) | 2021.04.20 |