팀원들과 함께하는 모던 JS 딥다이브 스터디 4차 💕
이번 스터디부터는 의문점이나 궁금한 점에 대해 정리하기로 했다.
1. var
키워드는 같은 스코프에서 중복 선언을 허용하지만,
let
, const
는 같은 스코프에서 중복 선언을 허용하지 않는다.
2. 동적스코프, 렉시컬스코프
3. 스코프체인
식별자가 유효한 범위
스코프 내에서 식별자는 유일해야 하지만,
var
키워드로 선언한 변수는 중복 선언을 허용한다.
var x = '하이'
var x = '바이'
console.log(x) // '바이'
console.log(window.x) // '바이'
console.log(window.x === x) // true
전역에서'var' 키워드로 선언된 변수는 window 객체의 프로퍼티
가 된다.
함수가 상위 스코프를 결정할 때의 방법
동적 스코프
: 함수가 호출되는 시점에 동적으로 스코프를 결정렉시컬 스코프
: 함수가 정의되는 시점에 정적으로 스코프를 결정 ✅const x = 'global'
function foo() {
const x = 'local'
bar()
}
function bar() {
console.log(x) // 'global'
}
foo();
JS는 렉시컬 스코프
를 따른다.
때문에 bar 함수를 foo 함수 내부에서 호출하더라도
bar 함수의 상위 스코프는 전역 스코프이다.
⚠️ ES3에서는 스코프 탐색을 list 참조를 따라 찾아가는 방식이었지만,
ES5부터는 outer의 참조를 활용한다.
Lexical Environment
는
environmentRecord
와 outer-Environment Reference
(편의상 outer)를 포함하고 있다.
outer
은 중첩 구조에서 상위에 있는 다른 Lexical Environment
를 가르키기 때문에
outer를 통해 Lexical nesting이 형성된다.
// (1) 전역 컨텍스트
let a = 1;
function outer() {
function inner() {
let a = 3;
}
inner(); // (3) inner 함수 실행
}
outer(); // (2) outer 함수 실행
⚠️ 스코프는 함수 객체가 생성될 때 결정된다.
즉 (함수 선언문에 경우) 함수 정의가 평가될 때 스코프가 결정된다.
function
키워드를 만나면 함수 객체를 생성하고
함수 객체의 [[Scopes]]
에 스코프를 설정한다.
함수가 호출되면 Lexical Environment의 outer
의 스코프 참조에 설정된다.
const hi = function () {}
console.log(hi.name)
이름이 없는 함수의 이름을 지정할 땐 컨텍스트에서 이름을 가져온다.
함수 몸체의 각 block은 고유한 lexical environment를 가진다.
이 부분은 이미 다 알고 있다고 생각했지만 역시나 세상엔 완벽한 건 없나보다 ㅎㅎ
하나의 실행 컨텍스트에 한 개의 렉시컬 환경만 생성된다고 생각했었지만,
오늘 팀원분께서 함수 내에서 블록 스코프가 있을 땐 블록 스코프의 렉시컬 환경이 또 생성되고,
for 문과 같이 블록 레벨로 반복문이 있을 땐 반복되는 개수만큼의 렉시컬 환경이 생성된다는 걸 알았다.
하지만 함수 호출로 실행 컨텍스트가 스택에 쌓이는 것은 아니기 때문에 overflow가 발생하진 않는다고 얘기가 결론이 났는데 나중에 좀 더 찾아봐야겠다.
자바스크립트 실행 컨텍스 (Execution Context)