[JavaScript] Scope?

so8san·2022년 10월 14일

JAVASCRIPT

목록 보기
4/8

Scope

Scope는 참조 대상 식별자(identifier, 변수, 함수의 이름과 같이 어떤 대상을 다른 대상과 구분하여 식별할 수 있는 유일한 이름)를 찾아내기 위한 규칙이다. 자바스크립트는 이 규칙대로 식별자를 찾는다.

변수는 전역 또는 코드 블록 (if, for, whle, try/catch 등)이나 함수 내에 선언합니다. 식별자는 자신이 어디에서 선언됐는지에 의해 자신이 유효한(다른 코드가 참조할 수 있는)범위를 갖습니다. 이 범위에 따라 코드가 참조가 가능할 수도 가능하지 않을 수도 있으며, 이와같은 규칙을 스코프라고 합니다.

만약 스코프가 없다면, 같은 식별자 이름은 모두 충돌을 일으키므로 프로그램 전체에서 하나밖에 사용할 수 없게 될 것입니다.

같은 이름의 파일을 한 곳에 둘 수 없는 것과 같습니다. 만약 디렉터리가 없다면 같은 이름의 폴더는 두개 이상 만들 수 없을 것 입니다.


🐣 쉽게 이해하기

Scope란 단어 자체를 직역하면 '범위' 라는 의미를 갖습니다. 컴퓨터 공학, javascript에서의 의미도 다르지 않습니다. 따라서 스코프는 범위를 뜻한다고 먼저 이해하고 읽는 편이 좋을 것 같습니다. 정의 자체는 "식별자 접근 규칙에 따른 유효 범위" 입니다.


Scope 구분

javascript에서의 scope는 다음과 같이 2가지로 나눌 수 있습니다.

전역 스코프 (Global scope)
코드 어디에서든지 참조할 수 있다.

지역 스코프 (Local scope or Functoin-level scope)
함수 코드 블록이 만든 스코프로 함수 자신과 하위 함수에서만 참조할 수 있다.

모든 변수는 스코프를 가지며, 변수의 관점에서 스코프를 구분한다면 다음과 같이 2가지로 나눌 수 있습니다.

전역 변수 (Global variable)
전역에서 선언된 변수이며 어디에든 참조할 수 있다.

지역 변수 (Local variable)
지역(함수)내에서 선언된 변수이며 그 지역과 그 지역의 하부 지역에서만 참조할 수 있다.

변수 스코프 규칙

변수는 "선언 위치(전역 or 지역)"에 의해 스코프를 가지게 됩니다.


전역에 위치해 전역 스코프를 갖게된 변수는 그 어디에서도 참조가 가능합니다. 하지만, 지역에 (block or function)에 속해 지역 스코프를 갖게된 변수는 그 지역과 그 지역의 하부 지역에서만 참조할 수 있습니다.

Scope 정리

javascript에서의 Scope는 타 언어와의 차이점이 있습니다.

예를 들어 C언어에서는 {block}level scope를 따릅니다. if문 {}안에 선언한 변수는 if문 내 {}에서만 참조가 가능합니다. 하지만 javascript는 function-level scope를 따릅니다. 참조하려는 function안에 if문이 있기만 하다면, if문 안에 선언된 변수라 할지라도 참조가 가능합니다.

단, ES6에 도입된 let 키워드를 사용하면 block-level scope를 사용할 수 있습니다


💡전역 스코프/ 함수 스코프

var 키워드로 선언한 전역 변수는 전역 개개체(Global Object) window의 프로퍼티 입니다.

var global = 'global';

function Fn(){
	var local = 'local';
  	console.log(global) //'global'
  	console.log(local) // 'local'
}
Fn()

console.log(global) //'global'
console.log(local) // ReferenceError

위와 같이 전역에서 선언된 global은 어디에서든 참조가 가능하지만, Fn함수 안에서 선언된 local은 function-level scope를 가지므로 안에서만 참조가 되고 바깥에서는 되지 않아서 참조에러가 뜨게됩니다.

!!!화살표 함수는 block-level scope로 취급됩니다!!!

💡비 블록 레벨 스코프

	if(ture){
   		var x = 1; 
    }

	console.log(x) // 1

위에 설명했든 javascript는 block-level scope가 아니라 function-level scope를 따릅니다. 따라서 function안에 선언된 변수가 아니라면 어디서든 참조가 가능합니다.
ES6부터 추가된 let키워드는 block-level scope를 갖습니다.

💡렉시컬 스코프

var x = 1;

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

function bar() { // 전역에 선언
	console.log(x) // 이 곳에서 x는 상위 끝까지 올라가서 x를 찾게된다. 따라서 test()에 선언된 x에게는 아무런 영향을 받지 않는다.
}

test(); // 1
bar(); // 1

위 예제를 실행하면 1,1 이 출력되는데 그 이유는 이미 실행 단계에서 코드들의 스코프를 결정 짓기 때문입니다. javascript는 렉시컬 스코프를 따르는데, 이 경우 함수를 선언한 위치를 기준으로 스코프를 결정 짓습니다. bar는 전역에 선언되어 있기 때문에. 전역에 선언되어있는 var x = 1을 참조하게 됩니다. 즉, test에서 bar를 호출한 시점은 아무런 영향을 주지 못합니다.

  1. 렉시컬 스코프는 함수를 어디서 호출하는지가 아니라 어디에 선언하였는지에 따라 결정됩니다.함수를 어디에서 호출하였는지는 스코프 결정에 아무런 영향을 주지 않습니다.
  2. 앞선 두 가지 방식으로 함수의 상위 스코프를 결정 짓는데 첫 번째 방식을 동적 스코프
    두 번째 방식을 렉시컬 스코프 또는 정적 스코프 라고 부릅니다.

🧠 생각

스코프는 범위라고 생각하면 되고, 변수를 선언하는 위치에 따라 변수를 참조할 수 있는 범위(스코프)가 주어지며, 변수를 참조할 때에는 지역변수가 우선순위를 갖는다 예를 들어 전역 변수를 함수 내에서 재할당하고 읽어드린다면, 전역에서 선언된 값이 아니라 읽을 때 위치와 가까운 재할당한 값이 출력된다. 화살표 함수는 function이 아니라 block으로 취급되니 유의할 것! 정도로 생각을 정리했다. 호이스팅 관련 글을 적을 때 스코프에 관련된 내용을 잘 모르고 정리해서 혼잡했던 내용들이 정리됐다.

참고 https://poiemaweb.com/js-scope

profile
늘 쌓아가는 중입니다.

0개의 댓글