[JS] 스코프에 대하여

정재은·2023년 4월 25일
0

JavaScript

목록 보기
13/15
post-thumbnail

📌 스코프(Scope)란?

식별자(변수, 함수, 클래스 이름)를 참조하거나 접근할 수 있는 유효한 범위
기본적으로 스코프란 범위, 영역을 뜻한다

스코프는 블럭에 의해 결정된다
블럭 내부의 변수는 블럭 내부에서만 유효하다
                           ↳ { } , if( ) { } , for( ) { } , function( ) { } 등


스코프 장점

① 변수의 이름 충돌을 방지하고
② 메모리를 절약할 수 있다
   (블럭 내부의 변수는 블럭이 끝나는 순간 메모리에서 제거되기 때문!)




스코프 포인트💡

변수는 최대한 필요한 블럭 내부에서 정의하는 것이 가장 좋다




예시

예시1 ) 블럭 외부에서는 블럭 내부의 a 변수를 참조할 수 없다

{
	const a = 'a';
	console.log(a);   // a
}
console.log(a);   // a is not defined

예시2 ) 함수 외부에서는 함수 내부의 message 변수를 참조할 수 없다

function print(){
	const message = 'HelloWorld';
	console.log(message);
}
print();   // HelloWorld
console.log(message);   // message is not defined

예시3 ) 함수 외부에서는 함수의 매개변수를 참조할 수 없다

function print(a){
	console.log(a)
}
print('print!')   // print!
console.log(a);   // a is not defined



문제

각각의 console은 어떤 값을 나타낼까?

문제1 )

{      // - - - - - - - - - - - - - - 첫번째 블럭
  const a = 1;
  {    // - - - - - - - - - - - - - - 두번째 블럭
  	const b = 2;
    console.log(a);  // console1
  };
  console.log(a);  // console2
  console.log(b);  // console3
};

정답 :
1
1
'b' is not defined


a는 첫번째 블럭 내부에서 유효하고, b는 두번째 블럭 내부에서 유효하다
그래서 console1, console2는 a의 값을 참조할 수 있다
b는 두번째 블럭에서만 유효한데 b를 호출한 console3은 첫번째 블럭에 있기 때문에 값을 참조할 수 없다


문제2 )

const name = '전역변수';   // 전역변수, 전역스코프
{
  const name = '지역변수1';   // 지역변수, 지역스코프
  {
  	const name = '지역변수2';
    console.log(name);
  };
};

정답 :
지역변수2


만약 참조하는 값이 현재 블럭에 없다면
한단계씩 상위 블럭으로 올라가면서 값을 찾는데, 가장 가까운 상위 블럭의 값을 참조하게 된다







📌 Garbage Collector (GC)

[ 얄코 - garbage_collector ]
[ 모던 JavaScript 튜토리얼 - garbage-collection ]

Garbage Collector(가비지컬렉터)는 자바스크립트 엔진에서 제공하는 백그라운드 프로세스로
우리가 직접적으로 메모리를 관리하지 않아도 알아서 정리해준다

주기적으로 변수가 메모리를 참조하고 있는 지 확인한 다음에
참조하고 있지 않으면 자동으로 메모리에서 지워버린다
단, 지워야할 것들을 100% 잡아내는 것은 아니다


Q. 아니 그래서 Garbage Collector랑 스코프랑 무슨 상관인데?
A. 예시를 보자!


예시 )

const global = 'global';
{
  const local = 'local';
};

global : 전역변수
local : 지역변수

위에서 말했듯이
전역변수는 앱이 종료될 때까지 계속해서 메모리에 유지되고,
지역변수는 블럭이 끝나면 메모리에서 제거되는데 → 이게 바로 Garbage Collector가 하는 일!
Garbage Collector에 의해 제거되는 것이다

전역변수 또한 선언해놓고 사용하지 않으면 불필요한 메모리를 차지하게 되는데
Garbage Collector가 이런점을 캐치하고 메모리에서 제거하여 정리해주는 것이다

⇒ 그래서 변수는 최대한 필요한 곳에서 정의하여 사용하는 것이 가장 좋다는 결론!







📌 호이스팅 Hoisting

호이스팅이란
자바스크립트 엔진이 코드를 실행하기 전에 변수, 함수, 클래스 선언문을 최상단으로 끌어올리는 것이다
'선언' 자체만 최상단으로 끌어올리기 때문에 할당된 값은 호이스팅 되지 않는다

함수, 변수, 클래스에서의 호이스팅은 조금씩 다르게 일어난다



1 ) 변수, 클래스의 호이스팅

console.log(hoisting_let);   // Cannot access 'hoisting_let' before initialization
let hoisting_let = 'let 키워드';


console.log(hoisting_Class);   // Cannot access 'hoisting_Class' before initialization
const hoisting_Class = new HoistingClass();
class HoistingClass {};

hoisting_let, hoisting_Class가 선언되기 이전에 호출한 상황

변수와 클래스는 선언 자체(이름)만 호이스팅 되고 초기화는 되지 않는다
그래서 초기화 이전에 선언만 된 변수에 접근하였기 때문에 컴파일 에러가 발생한다




2 ) 함수의 호이스팅

2-1. 함수 선언문

print1();   // HelloWorld
function print1(){
	console.log('HelloWorld');	
};

print1함수가 선언되기 이전에 호출한 상황

보다시피 함수 선언문에서는 호이스팅 일어난다

function print1(){
	console.log('HelloWorld');	
};
print1();   // HelloWorld

실제로는 이런 순서대로 읽어들이는 것!


2-2. 함수 표현식

print2();   // print2 is not a function
var print2 = function printFn(){
	console.log('HelloWorld');	
};

print2printFn함수가 선언되기 이전에 호출한 상황

함수 표현식으로 정의된 경우에는 호이스팅이 일어나지 않는다







📌 var 변수

var 키워드로 선언한 변수는 호이스팅이 일어날뿐만 아니라 undefined로 변수를 초기화한다
때문에 가독성과 유지보수에 좋지 않다


특징을 통해 살펴보자

특징1 ) 변수를 선언하는 키워드가 없어도 선언과 할당이 가능하다 → 선언인지 재할당인지 구분하기 어렵다

message = 'var변수의 특징';
console.log(message);   // var변수의 특징

특징2 ) 중복 선언이 가능하다

var apple = '사과';
var apple = '🍎';
console.log(apple);   // 🍎

특징3 ) 블록레벨 스코프가 완전히 무시된다 (지역변수가 전역변수와 같아지는 대참사 발생!)

var orange = '오렌지';
{
  var orange = '🍊';
  {
    var orange = 'orange';
  }
};
console.log(orange);   // orange

특징4 ) 함수 레벨 스코프만 지원된다

function print(){
  var banana = '🍌';
};
console.log(banana);   // banana is not defined





profile
프론트엔드

0개의 댓글