본문 바로가기
Language/JavaScript

JavaScript / 스코프(Scope)란?

by Krystal K 2022. 6. 22.

<Today's Goals>

  • 스코프란?
  • 스코프의 종류

<What i learned>

  • 전역변수와 지역변수를 구분할 수 있다.
  • 블록 레벨 스코프와 함수 레벨 스코프를 구분할 수 있다.
  • 전역변수와 지역변수가 중복 선언된 경우 실행되는 우선순위를 이해했다.

<Questions>

  • 스코프 체인(scope chain)이란?

스코프(Scope)란?

스코프는 변수가 영향을 미치는 범위, 혹은 변수의 유효범위에 대한 규칙이다.

식별자가 자신이 어디에서 선언됐는지에 의해 자신이 유효한 범위를 갖는다.

스코프는 이러한 참조 대상 식별자를 찾아내는 규칙이다.

더보기

참조 대상 식별자(identifier, 변수, 함수의 이름과 같이 어떤 대상을 다른 대상과 구분하여 식별할 수 있는 유일한 이름)

모든 변수는 스코프를 갖는다.


스코프의 종류

전역스코프(Global Scope)

  • 코드 어디에서든지 참조가 가능하다.
  • 전역변수는 어디서든 참조할 수 있는 전역 스코프를 갖는 변수이다.

지역스코프(Local scope / Function-level scope)

  • 함수 자신과 하위 함수에서만 참조가 가능하다.
  • 함수 내에서 선언된 매개변수와 변수는 함수 외부에서는 유효하지 않다.
  • 지역변수는 지역스코프를 갖는 변수이다.

위의 예시를 보면, global은 전역 변수로서 전역스코프를 갖고, local은 지역변수로서 지역스코프를 갖는다.

따라서 global은 scope함수 안에서도 참조가 가능하지만, local은 scope함수 밖에서 참조가 되지않는다.

따라서 consol에서 "Uncaught ReferenceError: local is not defined"가 뜨게 된다.


전역변수와 지역변수가 중복 선언된 경우

전역에서는 전역변수만이 참조가 가능하다.

함수 내에서는 전역과 지역변수 모두 참조가 가능하다.

위와 같은 상황에서 변수명이 중복될 경우, 지역변수를 우선한다.

x를 함수 밖에서 consol로 출력하면 "global"로 출력되지만 scope 함수 안에서 x를 "local"로 재선언 했기 때문에 "global"이 아닌 "local"로 출력된다. 또한 내부 함수인 scopein에서도 scope에서 선언했던 x 값 "local"을 그대로 상속받아 "local"로 출력하고 이후 다시 x를 100으로 선언하면 100이 출력되는 것을 볼 수 있다.

 

중첩 스코프는 가장 인접한 지역을 우선한다.

 


스코프의 특징에 따른 분류

 

블록레벨 스코프

코드 블록{} 내에서만 참조(접근)이 가능한 범위이다.

코드 블록 밖에서는 참조가 불가능하다.

 

함수레벨 스코프

함수 코드 블록 내에서만 참조(접근)이 가능한 범위이다.

 

 

대부분의 c기반 언어들은 블록레벨 스코프를 따른다.

하지만 자바스크립트는 함수 레벨 스코프를 따른다.

단, ECMAScript 6에서 도입된 let, const 를 사용하면 블록 레벨 스코프를 사용할 수 있다.

 

 

위의 예시를 보면, var와 let의 결과가 다르게 출력된다.

자바스크립트에서는 함수 밖에서 선언된 변수는 코드 블록 내에서 선언되었다 할지라도 모두 전역 스코프를 가지게 된다.

비 블록 레벨, 즉 함수 레벨 스코프이기 때문이다. 이러한 이유로 var를 사용해 선언된 x는 전역 변수로 작동하여  함수 밖에서 호출할 경우에도 "global"이 아닌  "local"로 출력된다.


자바스크립트는 lexically scoped. 

스코프를 결정할 수 있다. 

 

Nested Scoped & Function

자바스크립트는 nested blocks을 허용한다.

nested scopes는 scope tree 와 scope chain을 생성한다.

 

let, const 를 사용한 범위 지정

ES6에서 자바스크립트도 블록 스코프 변수를 생성할 수 있도록 함

단, let, const로 선언할 때만 가능

 

let

블록 스코프의 범위를 가지는 지역 변수 선언

선언과 동시에 임의의 값으로 초기화 가능

자신을 선언한 블록과 모든 하위 블록을 스스로의 스코프로 가진다.

var와 유사

 

var과의 차이점

var는 변수를 블록을 고려하지 않고 현재 함수 어디에서나 접근할 수 있는 변수 선언 (자신의 선언을 포함하는 함수 = 스코프)

프로그램 최상위에서 사용할 경우 전역 객체에 속성을 추가

 

let은 parser가 구문을 평가해야만 변수를 값으로 초기화 ( 자신을 선언한 블록 = 스코프)

프로그램 최상위에서 사용할 경우 전역 객체에 속성을 추가하지 않음

 

재선언

같은 변수를 같은 함수나 블록 스코프 안에서 다시 선언하려고 시도하면 syntaxerror 발생

-> 분기에 블록을 배치, 블록 스코프 생성으로 재선언 오류 해결

 

 

시간상의 사각지대 

let 변수는 초기화하기 전에는 읽거나 쓸 수 없다.

선언 구문에 초기값을 지정하지 않은 경우 undefined로 초기화

초기화 전 접근 시도시 referenceError 발생

 

변수 스코프의 맨 위에서 변수의 초기화 완료 시점까지의 변수는 "시간상 사각지대"(Temporal Dead Zone, TDZ)에 들어간 변수라고 표현

-> "시간상" 사각지대인 이유는, 사각지대가 코드의 작성 순서(위치)가 아니라 코드의 실행 순서(시간)에 의해 형성되기 때문

 

 


상위 스코프를 결정하는 방식에 따른 분류

동적 스코프(Dynamic Scope)

함수를 어디서 호출했는지에 따라 상위 스코프를 결정한다.

 

렉시컬 스코프(Lexical scope/Static scope)

함수를 어디서 선언했는지에 따라 상위 스코프를 결정한다.

자바스크립트 및 대부분의 프로그래밍 언어에서 사용하는 방식이다.

함수를 어디서 호출하든 영향을 받지 않는다.

 

 

 

 

 

 

728x90