스코프와 let, const

귤양·2021년 5월 26일
0

Javascript

목록 보기
6/10
post-thumbnail

아래 내용은 학원 수업과 "모던자바스크립트 Deep Dive : 이웅모 저"를 읽고 정리한 내용이다.

1. 스코프

스코프(scope)는 범위라는 뜻을 가지고 있다. 그렇다면 어떤 범위일까? 코드를 작성하면 변수 혹은 함수의 식별자들을 많이 작성하게 된다. 스코프는 바로 이 많은 식별자들을 검색하고 사용할 수 있는 범위를 말하는 것이고, 식별자가 선언된 위치에 따라서 결정된다. 만약 스코프가 없다면 어떤일이 발생할까? 식별자는 고유해야 하므로 프로그램 전체에서 하나밖에 사용할 수 없게된다. 스코프가 있는 지금도 식별자 네이밍이 힘든데.. 스코프가 없다면 정말 생각하기도 싫은 상황이 생길 것 같다.

스코프의 종류

스코프는 전역 스코프와 지역 스코프로 구분된다.

전역 스코프는 코드의 가장 바깥 영역인 전역이 만드는 스코프로 전역 스코프에 작성한 변수는 전역 변수가 되어 모든 영역에서 참조할 수 있다.

지역 스코프는 함수 몸체의 내부를 말하고, 지역 스코프 내부에서 선언한 변수는 지역 변수가 되고, 해당 지역 스코프와 그 지역 스코프에 속해 있는 하위 지역 스코프에서 참조할 수 있다.

스코프 체인

함수는 함수 몸체의 내부를 지역 스코프로 만든다. 또한 함수는 중첩이 가능하다. 따라서 스코프 또한 중첩이 가능하다는 뜻이다. 이 때 함수가 중첩되어 만든 스코프 중에 외부 함수가 만든 스코프를 상위 스코프, 내부 함수가 만든 스코프를 하위 스코프라고 한다. 이렇게 연결된 스코프의 구조를 스코프 체인이라고 하며, 변수(혹은 함수)를 참조(혹은 호출)할 때 자바스크립트 엔진은 스코프 체인을 따라 상위로만 이동하면서 변수를 검색한다.

그런데 변수를 검색할 때 단방향이 아닌 양방향이 검색이 가능하다고 가정해보자. 지금 현재 위치한 곳에서 변수를 검색하기 시작하여, 변수가 없으면 상위로 이동하며 검색하고 가상 상위 스코프인 전역 스코프에서 변수를 검색할 수 없을 때 다시 하위 스코프로 이동하며 변수를 검색하고 결국 계속 이러한 상황을 무한히 반복하게 되므로 문제가 생기게 되는 것이다. 때문에 스코프 체인은 단방향으로만 검색이 가능해야 하는 것이다.

렉시컬 스코프

자바스크립트의 함수는 함수를 정의한 위치에 따라서 상위 스코프를 결정한다. 이러한 스코프 결정 방식을 렉시컬 스코프라고 한다. 따라서 함수가 호출된 위치는 상위 스코프를 결정하는 것과는 전혀 상관이 없으며, 함수의 상위 스코프는 함수가 정의된 그 위치를 말한다.

2. let, const와 블록 레벨 스코프

ES6까지 변수를 선언하기 위해서는 var 키워드만을 사용해야 했고, 이렇게 var 키워드를 통해 선언한 변수는 여러가지 문제점들을 있었다. 이런 문제점을 해결하기 위해서 ES6에서 let, const가 나오게 되었다.

var 키워드로 선언한 변수의 문제점

  • var 키워드로 선언한 변수는 동일한 이름으로 변수를 선언하는 것이 가능했다. (나중에 선언한 변수는 재할당 한 것처럼 동작한다.)
  • var 키워드는 함수 레벨 스코프만을 인정하기 때문에 전역에서 var 키워드로 선언한 변수는 모두 전역 변수가 된다.
  • var 키워드로 선언한 변수는 호이스팅이 일어나서 변수를 선언하기 전에서 변수를 참조하는 것이 가능하다. (단, 변수 선언 이전에 참조한 변수는 undefined이다.)

변수에 호이스팅이 일어나서 변수를 선언하기 전에도 변수를 참조하는 것이 가능했다. 이런점들은 오류를 발생시킬 가능성이 높았기 때문에 ES6이후에 이런 단점들을 보완하기 위하여 let, const 키워드가 등장하게 되었다.

let, const 키워드

변수 중복 선언금지

let, const 키워드를 사용하여 변수를 중복선언하려고 하면 var 키워드와는 다르게 문법 에러가 발생한다.

블록 레벨 스코프

var 키워드로 선언된 변수가 지역 스코프를 만드는 것은 함수 밖에는 없었다. 하지만 let, const 키워드로 선언한 변수는 함수를 포함한 모든 코드 블록이 지역 스코프를 만든다.

변수 호이스팅

var 키워드로 선언한 변수는 호이스팅이 일어난다. 하지만 let, const 키워드로 선언한 변수는 호이스팅이 일어나지 않는 것처럼 동작하게 된다. 여기서 중요한 점은 호이스팅이 일어나지 않는 것이 아니라 일어나지 않는 것처럼 동작한다는 것이다.
let, const 역시 다른 선언문처럼 런타임 이전에 선언이 이루어진다. 그리고 var 키워드로 선언한 변수와 다르게 선언문이 작성된 시점에 와서야 초기화가 이루어지고 할당문이 작성되었을 때 값을 할당하게 된다. 이 때 런타임 이전에 이루어진 변수 선언과 변수의 초기화가 이루어지기 전까지의 사이에 변수를 참조할 수 없는 일시적 사각지대(Temporal Dead Zone : TDZ)가 생기게 되고, 이 사이에서 변수를 참조하려고 하면 에러가 발생하게 되는 것이다.

varlet, const
선언단계와 초기화동시에 일어남분리되어 일어남
선언 이전에 참조가능 (undefined 값이 참조됨)불가능 (에러가 발생함)

전역 객체와 let, const

var 키워드로 선언한 전역 변수와 선언하지 않은 변수에 값을 할당한 암묵적 전역은 전역 객체 window의 프로퍼티가 된다. 따라서 window.x와 같이 사용할 수 있다. (이 window는 생략하여 사용이 가능하다.) 하지만 let, const키워드로 선언한 변수는 window 전역 객체의 프로퍼티에 등록이 되지 않기 때문에 window.변수식별자와 같이 사용할 수 없다.

const 키워드

선언과 초기화

const 키워드로 선언한 변수는 선언과 동시에 초기화 해야 한다.

재할당 금지와 상수 그리고 객체

const 키워드로 선언한 변수는 var, let키워드로 선언된 변수와는 달리 재할당이 금지된다. 그리고 이렇게 재할당이 금지된 변수를 상수라고 한다. 만약 const 키워드로 선언한 변수에 원시값을 할당했다면 이 값을 변경할 방법은 없다. (원시값은 변경할 수 없는 값이기 때문에 재할당을 통해서만 값을 변경할 수 있는데, const키워드로 선언한 변수는 재할당이 불가능 하기 때문이다.) 하지만 만약 const 키워드로 선언한 변수에 객체를 할당할 경우 객체는 재할당을 하지 않아도 값을 변경할 수 있으므로 값을 변경할 수 있다. 따라서 const키워드는 재할당을 할 수 없다는 것이지 불변(immutable)을 의미하는 것이 아니다.

profile
디자인하는 Frontend Developer.

0개의 댓글