- 스코프란 무엇인가?
: 식별자 자신이 선언된 위치에 의해 함수 등의 다른 코드가 식별자 자신을 참조할 수 있는 유효 범위, 즉 쉽게 말하면 식별자가 유효한 범위
: 자바스크립트 엔진이 스코프를 통해 어떤 변수를 참조할지 결정함, 즉 식별자를 검색할 때 사용하는 규칙이기도 함
- 스코프는 왜 존재하는가?
: 식별자인 변수 이름의 충돌을 방지하기 위해
: 스코프를 구분하여 동일한 이름의 변수를 각각의 스코프에서 사용 가능
: 결국 스코프 개념이 없다면 동일한 이름의 변수는 프로그램 전체에서 하나만 사용 가능
- 스코프의 종류에는 무엇이 있고, 어떤 특징이 있는가?
: 전역 스코프와 지역 스코프
: 전역 스코프는 코드의 가장 바깥 영역을 의미함, 전역 스코프에 선언된 변수는 전역 변수이고 어디서든지 참조가 가능함
: 지역 스코프의 지역은 함수 몸체 내부를 의미함, 지역 스코프에 선언된 변수는 자신의 스코프와 하위에 있는 지역 스코프에서 참조가 가능함
- 스코프 체인이란 무엇인가?
: 함수가 중첩될 때 함수의 스코프도 계층적 구조를 가진다는 의미, 예를 들어 외부 함수 지역 스코프가 내부 함수 지역 스코프의 상위 스코프
: 결국 스코프 체인에 의해 모든 스코프는 하나의 계층적 구조로 연결됨
- 자바스크립트는 스코프 체인을 이용하여 구체적으로 어떻게 식별자를 검색하는가?
: 검색을 시작할 때를 기준으로 위치한 스코프에서 시작하여 상위 스코프 방향으로 계속 올라가면서 전역 스코프에 도달할 때까지 계속 식별자를 검색
: 상향식으로 검색하기 때문에 하위 스코프에서 상위 스코프를 참조하는 것은 가능하지만, 상위 스코프에서 하위 스코프를 참조하는 것은 불가능함
- 스코프 체인은 물리적으로 존재하는가?
: 자바스크립트 엔진이 코드를 실행하기에 앞서 렉시컬 환경을 생성하는데, 스코프 체인은 이 렉시컬 환경의 연결을 자료 구조화하여 나타낸 것이므로 물리적으로 존재함
- 함수 레벨 스코프란 무엇인가?
: 함수의 코드 블록(함수 몸체)만을 지역 스코프로 갖는 것
:let
,const
키워드가 추가된 ES6 이전의var
키워드가 존재했을 때는 함수 레벨 스코프만 존재했음
: 함수 레벨 스코프에서는 블록 레벨 스코프에서 선언된 변수가 전역 변수처럼 처리됨, 이 경우 의도치 않은 값이 재할당될 수 있음
- 렉시컬 스코프란 무엇인가?
: 정적 스코프라고도 함, 함수의 정의가 실행될 때 정적으로 정해지는 위치에 따라 함수의 상위 스코프가 결정되는 것
- 렉시컬 스코프가 필요한 이유는 무엇인가?
: 함수가 호출될 때마다 함수의 상위 스코프를 참조할 필요가 있기 때문
- 동적 스코프는 무엇인가?
: 렉시컬 스코프의 반대 개념으로 함수 호출되는 위치에 따라 함수의 상위 스코프를 결정하는 방식
: 의도치 않은 결과가 발생할 수 있기 때문에 대부분의 프로그래밍 언어에서는 렉시컬 스코프 방식을 따르고 있음
- 변수의 생명 주기란 무엇인가?
: 변수의 메모리 공간이 확보된 시점부터 메모리 공간이 해제되어 사용할 수 있는 메모리로 반환되는 시점까지를 의미함
- 지역 변수의 생명 주기는 어떻게 정해지는가?
: 지역 변수는 함수 호출 시 런타임 이전에 먼저 선언되어 초기화를 겪고 생명 주기가 시작됨
: 함수 호출 시 함수 블록의 실행 컨텍스트가 별개로 생성되고, 그 실행 컨텍스트의 렉시컬 환경에 선언된 지역 변수가 저장됨
: 만약 지역 변수를 더 이상 참조하지 않는 경우 사용할 수 있는 메모리로 반환되고, 스코프 역시 소멸하여 생명 주기가 종료됨
: 결국 지역 변수의 생명주기는 함수 호출 시 생성되고 함수 종료 시 소멸됨
- 전역 변수의 생명 주기는 어떻게 정해지는가?
: 전체 코드가 로드되자마자 전역 변수가 선언 및 초기화되므로 생명 주기가 생성되고, 전체 코드의 마지막 문이 실행되고 나서 더 이상 실행할 문이 없을 때 생명 주기가 종료됨
: 결국 전역 변수의 생명 주기는 전역 변수가 프로퍼티로 할당되는 전역 객체의 생명 주기와 일치함
- 전역 객체란 무엇인가?
: 코드 실행 이전에 자바스크립트 엔진에 의해 생성되는 특수한 객체
: 브라우저 환경에서는window
객체, 서버 사이드 환경(Node.js)에서는global
객체가 생성됨
: 전역 객체는 표준 빌트인 객체(Object
,String
,Number
등)와 환경에 따른 호스트 객체(Web API 등), 전역 변수와 전역 함수를 프로퍼티로 가짐
- 전역 변수 사용에는 어떤 문제점이 있는가?
: 전역 변수는 스코프 체인에 의해 내부 함수까지 암묵적 결합을 허용하기 때문에 코드 어디서든 참조할 수 있음, 즉 유효 범위가 커지기 때문에 가독성이 나빠지고 의도치 않게 상태가 변경되는 문제 발생
: 전역 변수는 생명 주기가 길기 때문에 메모리 리소스를 오랜 기간 소비하므로, 전역 변수의 상태를 변경할 수 있는 시간도 길고 기회도 많아서 변수 이름이 중복되거나 의도치 않은 재할당이 이뤄짐
: 스코프 체인 상에서 가장 마지막에 검색하는 종점에 존재하기 때문에 검색 속도가 가장 느리다는 단점이 있음
: 파일이 분리되어 있어도 하나의 전역 스코프를 공유하기 때문에 다른 파일에 있는 동일한 전역 변수, 전역 함수가 있으면 예상치 못한 결과 발생할 수 있음
- 전역 변수 사용을 어떻게 억제할 수 있는가?
: 코드를 즉시 실행 함수로 감싸면 지역 변수가 되고 그 변수는 한 번만 호출되고 사용되지 않기 때문에 전역 변수 사용을 억제할 수 있음
: 네임스페이스 역할을 담당하는 하나의 객체를 생성하고 전역 변수처럼 사용할 변수를 객체의 프로퍼티로 추가할 수 있음, 그러나 그 객체 역시 전역 변수의 프로퍼티로 할당되기 때문에 바람직한 방법은 아님
: 클래스처럼 관련 있는 변수와 함수를 즉시 실행 함수로 감싸서 모듈 패턴을 생성할 수 있음, 모듈 패턴을 사용하면 캡슐화의 기능까지 추가하여 내부 프로퍼티를 은닉할 수 있음
: ES6 모듈을 사용하면 파일별로 독자적인 모듈 스코프를 제공하기 때문에 전역 변수가 전역 스코프를 공유하지 않으므로 지역 변수처럼 사용할 수 있음
var
키워드로 선언한 변수는 어떤 문제가 있는가?: 변수의 중복 선언을 허용하기 때문에 의도치 않은 값의 변경이 이루어질 수 있음
: 함수 레벨 스코프를 지역 스코프로 가지기 때문에var
키워드로 선언한 변수는if
,for
등의 코드 블록 안에서 전역 변수로 처리됨
:var
키워드로 선언한 변수는 변수 호이스팅이 발생하는데, 이는 에러를 발생시키지 않지만 흐름에 맞지 않아서 가독성이 저하되고 오류를 발생시킬 여지가 있음
let
,const
키워드의 공통적인 특징은 무엇인가?:
let
,const
키워드로 선언한 변수는 변수 호이스팅이 발생하지 않는 것처럼 동작
:let
,const
키워드로 선언한 전역 변수는 더 이상 전역 객체의 프로퍼티가 아니고, 보이지 않는 개념적인 블록(전역 렉시컬 환경의 선언적 환경 레코드) 내에 존재함
:let
,const
키워드로 선언한 변수는 블록 레벨 스코프를 따르기 때문에 함수뿐만 아니라if
,for
,while
문 등 모든 코드 블록을 지역 스코프로 인정
let
키워드만의 특징은 무엇인가?:
let
키워드는 변수 선언 단계와 변수 초기화 단계가 분리되어 진행됨
- TDZ란 무엇인가?
:
let
키워드를 사용하여 변수를 선언하면 스코프 시작 지점부터 초기화 단계 시작 지점(변수 선언문)까지 변수를 참조할 수 없는 구간을 일시적 사각지대(TDZ)라고 함
const
키워드만의 특징은 무엇인가?:
const
는 변수 선언과 동시에 초기화해야 함, 즉 할당까지 함께 이루어져야 함
:let
과는 다르게 재할당이 불가능하다는 특징이 있으므로, 상수 선언을 위해 많이 사용함
:const
의 재할당이 불가능하기 때문에 원시 값을 변경(재할당)할 수 없지만, 객체는 참조 값이 중첩된 구조이므로 프로퍼티를 동적으로 생성하거나 삭제하는 등의 변경 가능
: 결국const
가 재할당을 금지한다는 것이 값의 불변을 의미하는 것은 아님
- 변수 선언 시 어떤 키워드를 사용하는 것이 바람직한가?
: ES6 이후 버전을 사용한다면
var
키워드는 사용하지 않아야 함
: 일단const
를 사용하고, 재할당이 필요한 경우let
으로 수정하는 방식으로 사용
:let
을 사용할 때 스코프는 최대한 좁게 설정해야 함
:const
는 읽기 전용으로 사용하는 원시 값과 객체에 사용하면 안전함