소스코드 실행 과정
평가단계 :자바스크립트가 소스코드를 스캔해서 선언문과 같은 식별자를 환경 레코드(Environment Record)라는 객체에 기록해둔다.
console.log(booung) // undefined
var booung = 1
var woowa = 2
console.log(booung) // 1
코드를 실행하는데 필요한 환경을 제공하는 객체
Variable Environment와 Lexical Environment는 실행 컨텍스트가 처음 실행될 때 동일한 렉시컬 환경을 참조하지만 소스코드를 평가하는 과정에서 새로운 렉시컬 환경이 생성되고, 둘의 참조는 달라지게 된다.
Variable Envrionment
Lexical Environment
→ var로 선언되는 변수와 let/cont로 선언되는 변수의 스코프가 다르기 때문
- This Binding
- this 키워드가 바인딩되는 객체 → 호출되는 방식에 따라 결정
var a = 10
function outer(){
var b = 20
// console.log(a,b,c)
function inner(){
var c = 30
console.log(a,b,c)
}
return inner()
}
outer() // 10, 20, 30
globalExecutionContext = {
lexicalEnvironment:{
environmentRecord: {
a: 10,
outer: <function>,
global: <global Object>,
},
outerEnvrionmentReference: null, -> 상위 스코프를 참조
},
}
outerExecutionContext = {
lexicalEnvironment:{
environmentRecord: {
b: 20,
inner: <function>,
},
outerEnvrionmentReference:
globalExecutionContext.lexicalEnvironment
},
}
innerExecutionContext = {
lexicalEnvironment:{
environmentRecord: {
c: 30,
},
outerEnvrionmentReference:
outerExecutionContext.lexicalEnvironment
},
}
코드 실행 단계 전에 모든 소스 코드의 함수와 변수 선언을 스캔하고 그 변수를 선언하고 초기화하고 할당한다. 이를 호이스팅이라 한다.
선언 : 변수를 실행 컨텍스트의 렉시컬 환경에 등록
초기화 : 등록된 변수를 위한 공간을 메모리에 확보. 이 단계에서 변수는 undefined로 초기화
할당 : undefined로 초기화된 변수에 실제 값을 재할당
var
console.log(a) // undefined
var a = 10
a //10
var a = 20
a // 20
let/const
함수 표현식 vs 함수 선언문
JS에서는 함수를 변수에 담아 사용할 수 있는데, 이 경우에는 변수 호이스팅과 같은 방식으로 동작하고 이를 함수 표현식이라 한다
const a = () => {console.log('react')}
const b = function(){
console.log('dev')
}
a() // react
b() // dev
그리고 변수에 담지 않고 함수를 선언하는 것을 함수 선언문이라 하는데, 이 경우에는 함수 선언과 동시에 f()함수가 생성이 된다. 그래서 함수 선언 이전에 함수가 호출에 되어도 레퍼런스 에러가 뜨지 않는다.
reactDev() //'react dev'
function reactDev(){
console.log('react dev')
}
식별자(변수)가 유효한 범위 → 변수 이름의 충돌을 방지
어디서든지 참조 가능
일정 스코프 내에서만 참조 가능
모든 코드 블록 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다. 즉, 코드 블록 내부에서 선언한 변수는 지역 변수이다.
변수르 참조할 때 항상 하위 스코프에서 상위 스코프로 이동한다.
함수를 어디서 정의했는지에 따라 함수의 상위 스코프를 정적으로 결정
함수를 어디서 호출했는지에 따라 함수의 상위 스코프를 결정
let은 블록스코프 내에서 재할당을 해도 바깥에서 선언한 것과는 다르게 동작한다. funciton스코프와도 마찬가지
외부 함수보다 중첩 함수가 더 오래 유지되는 경우 이미 생명주기가 종료한 외부 함수의 변수를 참조할 수 있는 중첩 함수
상위스코프의 식별자를 찹조하고 있고, 본인의 외부 함수보다 더 오래 살아있다면 이를 클로저라 한다.
그리고 클로저에 의해 참조된 변수를 자유 변수라 한다
var outer = function(){
var a= 1;
var inner = function(){
return ++a;
};
return inner
}
var playOuter = outer()
console.log(playOuter()) // 2
console.log(playOuter()) // 3
console.log(playOuter()) // 4
참조 카운트가 0이 되면 가비지 컬렉터의 수집 대상으로 없어짐 → 가비지컬렉터는 어떤 값을 참조하는 변수가 하나라도 있다면 수집 대상에 포함시키지 않는다.
자바스크립트 모든 함수는 상위 스코프를 기억한다. 그래서 이론적으로는 모든 함수가 클로저임
https://youtu.be/AlcRl4pJd0c?si=gLuUmX4QOb10XLpZ
https://youtu.be/8v-qFyJS8O8?si=x483VfruPrfsdUJq
https://youtu.be/KmpofpqkitA?si=LGmCml3LR2kIsOon
https://youtu.be/PVYjfrgZhtU?si=f6o2Dk0MkX_rzzXm
https://youtu.be/xJtVVLPxgco?si=cerFe0k79RCZbW-x
https://youtu.be/bwwaSwf7vkE?si=KICvwy-6GYR2K9Qz
https://youtu.be/QkCNba92Vqo?si=FyZU0bc615i-6iJd
https://velog.io/@cjkangme/JS-LexicalEnvironment-vs-VariableEnvironment
https://hanamon.kr/javascript-호이스팅이란-hoisting/
https://velog.io/@1nthek/JavaScript-변수와-함수-호이스팅Hoisting에-대해-알아보자