자바스크립트 (10)

Do_Doolly·2022년 12월 11일
0

자바스크립트 TIL

목록 보기
10/15
post-thumbnail
post-custom-banner
  • 글에 적은 내용 중 잘못된 부분은 댓글로 적어주시면 감사하겠습니다!

🔜 지역변수와 전역변수

프로그래밍 언어를 공부하다 보면 한 번쯤 듣게되는 것 중에 지역변수와 전역변수가 있다.

한글로 풀이돼있으니 대충 짐작해보자면 지역변수는 특정한 지역 내에서만 쓰이는 변수고, 전역변수는 전체 범위에서 쓰이는 변수라는 걸 알 수 있다.

호텔을 예로 들자면 적절한 비유인지 모르겠지만 🙄 각 객실에서는 모든 로비에 접근할 수 있다. 하지만 객실끼리는 서로 접근할 수 없다.

여기서 로비는 전역변수, 객실은 지역변수라고 보면 된다.

언어마다 다르지만 보통 전역변수는 함수와 동일 레벨의 코드 상에서 선언되고, 지역변수는 함수나 블록 내부에 선언해서 사용한다.

🧐 유효범위 (Scope)

예전에 올린 자바스크립트 포스팅중에 변수의 유효범위에 대한 내용이 있다.[1]

유효범위를 스코프라고 보통 부르므로 앞으로 스코프로 통일하겠다.

var, let, const의 차이에 대해 설명하면서 var는 함수 스코프나 전역 스코프를 갖는 반면에 let과 const는 블록 스코프를 갖는다고 했다.

그럼 이제 각각의 스코프의 차이는 뭐고 어떻게 사용되는지 알아보자

1. 스코프의 정의

스코프는 참조 대상 식별자를 찾아내기 위한 규칙이다. 또한 변수의 수명을 의미하기도 한다.

맨 위에 있는 짤에서 볼 수 있듯이, 변수의 수명을 벗어난 곳에서 해당 변수를 사용하게 되면 에러가 뜨거나 undefined가 나올 것이다.

특히 자바스크립트는 동적 타이핑 언어로 다른 언어와 달리 타입을 별도로 지정하지 않고, 쉽게 전역 변수를 설정하고 다시 변수 초기화를 할 수 있기 때문에 스코프에 유의해야 한다!

function fscope() {
  var say = 'hi';
  console.log(say);
}

fscope();				// hi
console.log(say);		// Reference Error

2. 전역 스코프

전역 스코프는 애플리케이션 전역에서 사용할 수 있는 범위를 가진다.

내가 만든 A함수, B함수, C클래스 어디서나 접근할 수 있다. 공통적으로 접근할 수 있다보니 필요할 때는 유용할 수 있지미나, 대개의 경우 변수명이 충돌하여 의도치 않은 값을 만들거나 에러가 발생할 수 있어 가급적 사용하지 않는 것을 추천한다.

전역 스코프를 가진 변수를 선언한다면 var나 let과 같이 변경할 수 있는 값이 아니라 const와 같이 변경하지 못하는 상수 값으로 설정하는게 좋다.

자바스크립트에서 var 는 전역 스코프로 선언할 경우 전역 객체 (window)의 프로퍼티가 된다.

🚫 아래 코드는 무한반복을 발생시킨다

function a() {
  i = 0;
}

for (var i = 0; i < 5; i++) {
  a();
  console.log(i);			// 0만 무한히 출력
}

위 코드에서 var로 선언된 i라는 변수가 문제를 일으킨다. 다른 언어에서는 문제가 안될 수 있지만, 자바스크립트에서 var로 선언된 변수가 다른 곳에서 초기화될 경우, 현재 함수나 모듈에서 문제를 일으킬 수 있다.

3. 함수 스코프

함수 스코프는 함수 내에서만 사용할 수 있는 범위를 가진다.

보통 다른 프로그래밍 언어에서 사용되는 블록 스코프와 의미가 조금 다르다.

자바에서 함수 내에서 변수를 사용할 때 블록( { or } )단위로 변수가 정의되기 때문에, 외부 범위에서는 해당 변수를 참조할 수 없다.

static void test() {
  if(true) {
    int a = 1;
  }
  
  System.out.println(a);
}

test();				// Reference Error

하지만 자바스크립트에서는 이게 가능하다!

함수 스코프에서는 함수 코드 블록 내에서 선언된 변수는 함수 블록 내부에서 유효하고 외부에서만 참조할 수 없기 때문이다.

function fscope() {
  // if문 내에 say 변수 선언
  var say;
  if (true) {
    var say = 'hi';
  }

  console.log(say);
}

fscope();			// hi
console.log(say);	// Reference Error

4. 블록 스코프

ES6 이전에는 var로만 변수를 선언했기 때문에 스코프가 전역 스코프와 함수 스코프로만 나뉘었다.

그러나 ES6 이후로 let과 const가 도입됨에 따라 블록 스코프를 사용할 수 있다.

// 함수 스코프를 가진 var
var x = 0;
{
  var x = 1;
  console.log(x);		// 1
}
console.log(x);			// 1

// 블록 스코프를 가진 let
let y = 1;
{
  let y = 2;
  console.log(y);		// 2
}
console.log(y);			// 1

🔚 렉시컬 스코프

마지막으로 함수의 상위 스코프를 결정하는 방법을 알아보자.

var x = 1;

function foo() {
  var x = 10;
  bar();
}

function bar() {
  console.log(x);
}

foo();					// ?
bar();					// ?

위 예제에서 실행 결과는 함수 bar의 상위 스코프가 무엇인지에 따라 결정된다.

함수를 어디서 호출했는지에 따라 상위 스코프를 결정하면 10이 출력될 것이고, 함수를 어디서 선언했는지에 따라 상위 스코프를 결정하면 1이 출력될 것이다.

첫 번째 방법을 동적 스코프(Dynamic Scope)라 하고, 두 번째 방법을 렉시컬 스코프(Lexical Scope) 혹은 정적 스코프(Static Scope)라 한다.

자바스크립트를 비롯한 대부분의 프로그래밍 언어는 렉시컬 스코프를 따른다.

따라서 위 예제에서 자바스크립트의 경우 1이 출력된다. 만약 동적 스코프를 따르는 경우라면 10이 출력될 것이다.


스코프에 대해서는 이해가 깊이 필요한 것 같다. 특히 자바스크립트는 컴파일 언어와 달리 즉시 코드를 읽으며 실행되는 인터프리터 언어이기 때문에 전역변수를 남발하여 사용할 경우 심각한 문제가 발생할 수 있다.

부득이하게 전역변수를 사용할 경우 더글라스 크락포드가 제안한 전역변수 객체화와 즉시실행함수(IIFE)를 이용한 방법으로 최대한 안전하게 사용해야 한다.



& 자바스크립트 참고 강의 링크

생활코딩 JavaScript
드림코딩 JavaScript 기초 강의
모던 자바스크립트 - 스코프


주석

[1] : 자바스크립트 변수

profile
생각하면 복잡하니까 일단 해보자
post-custom-banner

0개의 댓글