πŸ“š μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ

thumb_hyeokΒ·2022λ…„ 3μ›” 1일
0

🟑 JavaScript

λͺ©λ‘ 보기
3/15
post-thumbnail

πŸ€” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλž€ λ¬΄μ—‡μΌκΉŒ?

μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ

μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진은 μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜κΈ° 전에 μ½”λ“œλ₯Ό ν‰κ°€ν•˜λŠ” 과정을 κ±°μΉœλ‹€. κ·Έ 후에 선언문을 μ œμ™Έν•œ μ†ŒμŠ€μ½”λ“œκ°€ μ‹€ν–‰λœλ‹€. 이 λ•Œ, μ½”λ“œλ₯Ό ν‰κ°€ν•˜λŠ” κ³Όμ •μ—μ„œ μ†ŒμŠ€μ½”λ“œλ₯Ό μ‹€ν–‰ν•  λ•Œ μ œκ³΅ν•  ν™˜κ²½ 정보λ₯Ό λͺ¨μ•„놓은 객체λ₯Ό μƒμ„±ν•˜λŠ”λ° 이 객체가 μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ΄λ‹€.


μ†ŒμŠ€μ½”λ“œμ˜ νƒ€μž…

μ†ŒμŠ€μ½”λ“œλŠ” ECMAScript 사양에 따라 4가지 νƒ€μž…μœΌλ‘œ κ΅¬λΆ„λœλ‹€. 4가지 νƒ€μž…μ˜ μ†ŒμŠ€μ½”λ“œλŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλ₯Ό μƒμ„±ν•œλ‹€. (μ½”μ–΄ μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” ES6λΆ€ν„°λŠ” 블둝에 μ˜ν•΄μ„œλ„ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ μƒμ„±λœλ‹€κ³  ν•œλ‹€. κ·ΈλŸ¬λ‚˜ λͺ¨λ˜ μžλ°”μŠ€ν¬λ¦½νŠΈ Deep DiveλŠ” 블둝에 μ˜ν•΄μ„œλŠ” μƒˆλ‘œμš΄ LexicalEnvironment만 μƒμ„±λ˜μ–΄ μ½”λ“œ 블둝이 μ‹€ν–‰λ˜λŠ” λ™μ•ˆ κ΅μ²΄ν•œλ‹€κ³  ν•œλ‹€. μ–΄λŠ μͺ½μ΄ λ§žλŠ”μ§€ λͺ¨λ₯΄κ² λ‹€. ()μ•ˆμ˜ λ‚΄μš©μ€ 아직 이해가 μ•ˆ λ˜μ–΄λ„ 상관없닀. λ‚˜μ€‘μ— 글을 λ‹€ 읽고 ν•œ 번 μ˜¬λΌμ™€μ„œ μ‚΄νŽ΄λ§Œ 봐라.)

μ „μ—­ μ½”λ“œ, ν•¨μˆ˜ μ½”λ“œ, eval μ½”λ“œ, λͺ¨λ“ˆ μ½”λ“œλ‘œ κ΅¬λΆ„λœλ‹€.

이 κΈ€μ—μ„œλŠ” μ „μ—­ μ½”λ“œμ™€ ν•¨μˆ˜ μ½”λ“œλ‘œ μƒμ„±λ˜λŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλ§Œ 닀루도둝 ν•˜κ² λ‹€.

μ „μ—­ μ½”λ“œλŠ” μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλ₯Ό μƒμ„±ν•˜κ³ , ν•¨μˆ˜ μ½”λ“œλŠ” ν•¨μˆ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλ₯Ό μƒμ„±ν•œλ‹€. 일단 μ—¬κΈ°κΉŒμ§€λ§Œ μ•Œκ³ , λ‘˜μ΄ 뭐가 λ‹€λ₯Έμ§€λŠ” μ•„λž˜μ—μ„œ μ‚΄νŽ΄λ³΄λ„λ‘ ν•˜μž.


πŸ“š Call stack (μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ μŠ€νƒ)

μƒμ„±λœ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλŠ” 콜 μŠ€νƒμ„ ν†΅ν•΄μ„œ κ΄€λ¦¬λœλ‹€. 맨 μœ„μ—μ„œ μ„€λͺ…ν•œ μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진에 μ˜ν•΄ μ†ŒμŠ€μ½”λ“œλŠ” 평가(Creation Phase), μ‹€ν–‰(Execution Phase) 두 λ‹¨κ³„λ‘œ λ‚˜λ‰˜μ–΄ μ²˜λ¦¬λœλ‹€κ³  ν–ˆλŠ”λ° 이에 λŒ€ν•œ 흐름에 집쀑해 μ•„λž˜ μ½”λ“œλ₯Ό μ‚΄νŽ΄λ³΄λ©΄ 쒋을 것 κ°™λ‹€. 그럼 μ•„λž˜μ˜ μ˜ˆμ‹œ μ½”λ“œμ˜ λ™μž‘μ„ λ³΄λ©΄μ„œ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ μ–΄λ–»κ²Œ λŒμ•„κ°€λŠ”κ±΄μ§€ μ’€ 더 μ°λ¨Ήν•΄λ³΄μž.

//---- 1 
const a = 1;

function foo() {
  const b = 2;
  
  console.log(b); //---- 3
}

foo(); //---- 2
console.log(a); //---- 4

주석을 달아 놓은 μˆœμ„œλŒ€λ‘œ μ½”λ“œ 진행을 μ„€λͺ…ν•˜λ„λ‘ ν•˜κ² λ‹€.

  1. μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ 생성
    μ „μ—­ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜κΈ°μ— μ•žμ„œ λ¨Όμ € μ „μ—­ μ½”λ“œ 평가 과정을 거치고 μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλ₯Ό μƒμ„±ν•œλ‹€. μƒμ„±ν•œ μ „μ—­ μ»¨ν…μŠ€νŠΈλŠ” 콜 μŠ€νƒμ— μŒ“μΈλ‹€. 콜 μŠ€νƒ 맨 μœ„μ— μŒ“μ—¬μžˆλŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλŠ” μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ΄κΈ° λ•Œλ¬Έμ— μ „μ—­ μ½”λ“œκ°€ μ‹€ν–‰λœλ‹€.

  2. foo ν•¨μˆ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ 생성
    μ „μ—­ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λ‹€κ°€ foo();λ₯Ό λ§Œλ‚˜λ©΄ μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진은 foo ν•¨μˆ˜ μ½”λ“œλ₯Ό 평가해 foo ν•¨μˆ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλ₯Ό μƒμ„±ν•œλ‹€. μƒμ„±ν•œ foo ν•¨μˆ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλŠ” 콜 μŠ€νƒμ— μŒ“μΈλ‹€. 이제 콜 μŠ€νƒ 맨 μœ„μ— μŒ“μ—¬μžˆλŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλŠ” μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ μ•„λ‹ˆλΌ foo ν•¨μˆ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ λ˜μ—ˆλ‹€. μ „μ—­ μ½”λ“œμ˜ 싀행은 μ€‘μ§€λ˜κ³ , foo ν•¨μˆ˜ λ‚΄λΆ€ μ½”λ“œκ°€ μ‹€ν–‰λœλ‹€.

  3. foo ν•¨μˆ˜ μ‹€ν–‰ μ’…λ£Œ
    console.log(b)λ₯Ό μ‹€ν–‰ν•˜κ³  λ‚˜λ©΄ foo ν•¨μˆ˜μ˜ 싀행이 μ’…λ£Œλ˜λ©΄μ„œ foo ν•¨μˆ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ 콜 μŠ€νƒμ—μ„œ μ œκ±°λœλ‹€. 이제 콜 μŠ€νƒ 맨 μœ„μ— μŒ“μ—¬μžˆλŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλŠ” μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ΄κΈ° λ•Œλ¬Έμ— 싀행을 μ€‘λ‹¨ν–ˆλ˜ foo(); μ€„μ˜ λ‹€μŒ 쀄뢀터 μ΄μ–΄μ„œ μ‹€ν–‰λœλ‹€.

  4. μ „μ—­ μ½”λ“œ μ‹€ν–‰ μ’…λ£Œ
    console.log(a)λ₯Ό μ‹€ν–‰ν•˜κ³  λ‚˜λ©΄ μ „μ—­ μ½”λ“œμ˜ 싀행이 μ’…λ£Œλ˜λ©΄μ„œ μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ 콜 μŠ€νƒμ—μ„œ μ œκ±°λœλ‹€. 콜 μŠ€νƒμ—λŠ” 아무것도 남지 μ•Šμ€ μƒνƒœλ‘œ ν”„λ‘œκ·Έλž¨μ€ μ’…λ£Œλœλ‹€.

이처럼 콜 μŠ€νƒμ€ μ½”λ“œμ˜ μ‹€ν–‰ μˆœμ„œλ₯Ό κ΄€λ¦¬ν•œλ‹€. μ†ŒμŠ€μ½”λ“œκ°€ ν‰κ°€λ˜λ©΄ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ μƒμ„±λ˜κ³  콜 μŠ€νƒμ˜ μ΅œμƒμœ„μ— μŒ“μΈλ‹€. 콜 μŠ€νƒμ˜ μ΅œμƒμœ„μ— μ‘΄μž¬ν•˜λŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλŠ” μ–Έμ œλ‚˜ ν˜„μž¬ μ‹€ν–‰ 쀑인 μ½”λ“œμ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ΄λ‹€. 콜 μŠ€νƒμ— μ΅œμƒμœ„μ— μ‘΄μž¬ν•˜λŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλ₯Ό μ‹€ν–‰ 쀑인 μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ(running excution context)라고 λΆ€λ₯Έλ‹€.


πŸ—ƒοΈ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ κ΅¬μ„±μš”μ†Œ

μœ„μ—μ„œλŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ μ½”λ“œλ₯Ό ν‰κ°€ν•˜λŠ” κ³Όμ •μ—μ„œ μ†ŒμŠ€μ½”λ“œλ₯Ό μ‹€ν–‰ν•  λ•Œ μ œκ³΅ν•  ν™˜κ²½ 정보λ₯Ό λͺ¨μ•„놓은 객체 라고만 μ–˜κΈ°ν•΄λ†“κ³  μ–΄λ–€ ν™˜κ²½ 정보λ₯Ό λͺ¨μ•„놓은건지 ν•˜λ‚˜λ„ μ„€λͺ…ν•˜μ§€ μ•Šμ•˜λ‹€. 이제 μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ κ΅¬μ„±μš”μ†Œλ₯Ό μ‚΄νŽ΄λ³΄λ©΄μ„œ μ‚΄νŽ΄λ³΄μž.

μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλŠ” VariableEnvironment, LexicalEnvironment μ»΄ν¬λ„ŒνŠΈλ‘œ κ΅¬μ„±λœλ‹€. (사싀은 이것보닀 더 λ³΅μž‘ν•œ ꡬ쑰λ₯Ό 가지고 μžˆλ‹€..) ꡬ쑰λ₯Ό μ‚΄νŽ΄λ³΄μžλ©΄ μ•„λž˜μ™€ κ°™λ‹€.

  • VariableEnvironment (LexivalEnvironment와 ꡬ쑰 κ°™μŒ)
  • LexicalEnvironment
    • EnvironmentRecord
      • ObjectEnvironmentRecord (μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλ§Œ μ‘΄μž¬ν•¨)
      • DeclarativeEnvironmentRecord (μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλ§Œ μ‘΄μž¬ν•¨)
      • [[ThisValue]] (μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλŠ” [[GlobalThisValue]])
    • OuterLexicalEnvironmentReference

각각이 μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ 객체가 생성될 λ•Œ μ–΄λ–€ ν™˜κ²½ 정보λ₯Ό λͺ¨μ•„ λ†“λŠ”μ§€, 무슨 역할을 ν•˜λŠ”μ§€λŠ” μ•„λž˜μ—μ„œ μˆœμ„œλŒ€λ‘œ μ‚΄νŽ΄λ³΄λ„λ‘ ν•˜μž.


πŸ—‚οΈ VariableEnvironment

VariableEnvironmentλŠ” ν˜„μž¬ μ»¨ν…μŠ€νŠΈ λ‚΄λΆ€μ˜ μ‹λ³„μžλ“€μ— λŒ€ν•œ 정보, μƒμœ„ μŠ€μ½”ν”„μ— λŒ€ν•œ μ°Έμ‘°λ₯Ό κΈ°λ‘ν•˜λŠ” μžλ£Œκ΅¬μ‘°μ΄λ‹€. μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ 생성될 λ•Œ, VariableEnvironment에 λ‹΄κΈ°λŠ” λ‚΄μš©μ€ LexicalEnvironment와 κ°™μ§€λ§Œ, 졜초 μ‹€ν–‰ μ‹œμ˜ μŠ€λƒ…μƒ·μ„ μœ μ§€ν•œλ‹€λŠ” 점이 λ‹€λ₯΄λ‹€. VariableEnvironmentκ°€ μƒμ„±λ˜κ³  이λ₯Ό κ·ΈλŒ€λ‘œ 볡사해 LexicalEnvironmentλ₯Ό λ§Œλ“€κ³  μ΄ν›„μ—λŠ” 주둜 LexicalEnvironmentλ₯Ό ν™œμš©ν•˜κ²Œ λœλ‹€.
(μ΄λŠ” μ½”μ–΄ μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ μ„€λͺ…인데, λ”₯ λ‹€μ΄λΈŒμ™€λŠ” λ‹€λ₯Έ 뢀뢄이 κ½€ μžˆλ‹€. μΆ”κ°€λ‘œ κ³΅λΆ€ν•΄μ„œ μ•Œμ•„λ‚΄λŠ” λ‚΄μš©μ΄ 있으면 더 적도둝 ν•˜κ² λ‹€)

κ·Έλž˜μ„œVariableEnvironment에 λŒ€ν•œ μ„€λͺ…은 μ—¬κΈ°κΉŒμ§€λ§Œ ν•˜κ³  μžμ„Έν•œ 사항은 μ²˜μŒμ—λŠ” κ°™μ§€λ§Œ μ½”λ“œ 진행에 따라 λ‹¬λΌμ§€κ²Œ 될 LexicalEnvironmentμ—μ„œ 닀루도둝 ν•˜κ² λ‹€.
그리고 이 κΈ€μ—μ„œλŠ” λ‘˜μ„ κ΅¬λΆ„ν•˜μ§€ μ•Šκ³  LexicalEnvironment으둜 톡일해 κ°„λž΅ν•˜κ²Œ μ„€λͺ…ν•˜κ² λ‹€.


πŸ—‚οΈπŸ–¨οΈ LexicalEnvironment

LexicalEnvironmentλŠ” VariableEnvironment와 λ§ˆμ°¬κ°€μ§€λ‘œ ν˜„μž¬ μ»¨ν…μŠ€νŠΈ λ‚΄λΆ€μ˜ μ‹λ³„μžλ“€μ— λŒ€ν•œ 정보, μƒμœ„ μŠ€μ½”ν”„μ— λŒ€ν•œ μ°Έμ‘°λ₯Ό κΈ°λ‘ν•˜λŠ” μžλ£Œκ΅¬μ‘°μ΄λ‹€. LexicalEnvironmentλŠ” 킀와 값을 κ°–λŠ” 객체 ν˜•νƒœμ˜ μŠ€μ½”ν”„λ₯Ό μƒμ„±ν•˜μ—¬ μ‹λ³„μžλ₯Ό ν‚€λ‘œ λ“±λ‘ν•˜κ³  μ‹λ³„μžμ— λ°”μΈλ”©λœ 값을 κ΄€λ¦¬ν•œλ‹€. 콜 μŠ€νƒμ΄ μ½”λ“œμ˜ μ‹€ν–‰ μˆœμ„œλ₯Ό κ΄€λ¦¬ν•œλ‹€λ©΄ LexicalEnvironmentλŠ” μŠ€μ½”ν”„μ™€ μ‹λ³„μžλ₯Ό κ΄€λ¦¬ν•œλ‹€.

EnvironmentRecord

LexicalEnvironment의 EnvironmentRecord μ»΄ν¬λ„ŒνŠΈμ—λŠ” ν˜„μž¬ μ»¨ν…μŠ€νŠΈμ™€ κ΄€λ ¨λœ μ½”λ“œμ˜ μ‹λ³„μž 정보듀이 μ €μž₯λœλ‹€. ν•¨μˆ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ 경우 ν•¨μˆ˜ λͺΈμ²΄ λ‚΄λΆ€μ—μ„œ μ„ μ–Έλœ λ³€μˆ˜, ν•¨μˆ˜, arguments객체, λ§€κ°œλ³€μˆ˜κ°€ λ“±λ‘λ˜μ–΄ κ΄€λ¦¬λœλ‹€. EnvironmentRecord λ‚΄λΆ€ 슬둯 [[ThisValue]]μ—λŠ” thisκ°€ λ°”μΈλ”©λœλ‹€. (this에 λŒ€ν•΄μ„œλŠ” λ‹€μŒμ— μ•Œμ•„λ³΄λ„λ‘ ν•˜κ² λ‹€.)

μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλŠ” 쑰금 λ‹€λ₯΄λ‹€. μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ EnvironmentRecordλŠ” μ „μ—­ λ³€μˆ˜λ₯Ό κ΄€λ¦¬ν•˜λŠ” μ „μ—­ μŠ€μ½”ν”„, μ „μ—­ 객체의 빌트인 μ „μ—­ ν”„λ‘œνΌν‹°μ™€ 빌트인 μ „μ—­ν•¨μˆ˜, ν‘œμ€€ 빌트인 객체λ₯Ό μ œκ³΅ν•œλ‹€. var둜 μ„ μ–Έν•œ μ „μ—­ λ³€μˆ˜λŠ” μ „μ—­ 객체의 ν”„λ‘œνΌν‹°κ°€ λ˜μ§€λ§Œ let,const둜 μ„ μ–Έν•œ μ „μ—­ λ³€μˆ˜λŠ” 그렇지 μ•Šλ‹€.
이 λ‘˜μ„ ꡬ뢄해 κ΄€λ¦¬ν•˜κΈ° μœ„ν•΄ μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ EnvironmentRecordλŠ”
ObjectEnvironmentRecord와 DeclarativeEnvironmentRecord둜 κ΅¬μ„±λ˜μ–΄μžˆλ‹€.

ObjectEnvironmentRecordλŠ” BindingObject라고 λΆ€λ₯΄λŠ” 객체와 μ—°κ²°λœλ‹€. μ΄λŠ” μ „μ—­ μ½”λ“œλ₯Ό ν‰κ°€ν•˜κΈ° 전에 μƒμ„±λœ μ „μ—­ 객체이닀. μ „μ—­ μ½”λ“œ 평가 κ³Όμ •μ—μ„œ var ν‚€μ›Œλ“œλ‘œ μ„ μ–Έλœ μ „μ—­ λ³€μˆ˜μ™€ ν•¨μˆ˜ μ„ μ–Έλ¬ΈμœΌλ‘œ μ •μ˜λœ μ „μ—­ ν•¨μˆ˜λŠ” μ „μ—­ 객체의 ν”„λ‘œνΌν‹°μ™€ λ©”μ„œλ“œκ°€ λœλ‹€.

DeclarativeEnvironmentRecordλŠ” let, const ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ μ „μ—­ λ³€μˆ˜μ™€ let, const ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ μ „μ—­ λ³€μˆ˜μ— ν• λ‹Ήν•œ ν•¨μˆ˜ ν‘œν˜„μ‹μ„ 등둝해 κ΄€λ¦¬ν•œλ‹€.

λ§ˆμ§€λ§‰μœΌλ‘œ EnvironmentRecord의 [[GlobalThisValue]] λ‚΄λΆ€ μŠ¬λ‘―μ— thisκ°€ λ°”μΈλ”©λœλ‹€.

OuterEnvironmentReference

OuterEnvironmentReferenceλŠ” ν•¨μˆ˜ μ •μ˜κ°€ ν‰κ°€λœ μ‹œμ μ— μ‹€ν–‰ 쀑인 μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ LexicalEnvironment, 즉 μƒμœ„ μŠ€μ½”ν”„λ₯Ό 가리킨닀. 이λ₯Ό 톡해 μ €λ²ˆ κΈ€μ—μ„œ μ•Œμ•„λ΄€λ˜ μŠ€μ½”ν”„ 체인이 단방ν–₯ μ—°κ²° 리슀트둜 κ΅¬ν˜„λœλ‹€. ν˜Ήμ‹œ μŠ€μ½”ν”„ μ²΄μΈμ΄λ‚˜, λ ‰μ‹œμ»¬ μŠ€μ½”ν”„μ— λŒ€ν•΄ μ •ν™•νžˆ λͺ¨λ₯΄κ² λ‹€λ©΄ 이전 글을 읽고 μ˜€λŠ” 것을 μΆ”μ²œν•œλ‹€.

➑️ μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ μŠ€μ½”ν”„


🎈 EnvironmentRecord 와 ν˜Έμ΄μŠ€νŒ…

ν˜Έμ΄μŠ€νŒ…μ΄λž€, μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진에 μ˜ν•΄ λ³€μˆ˜μ˜ μ„ μ–Έκ³Ό μ΄ˆκΈ°ν™” 단계가 λΆ„λ¦¬λ˜μ–΄ 진행될 λ•Œ, λ³€μˆ˜μ˜ μ„ μ–Έ λ‹¨κ³„λ•Œ λ³€μˆ˜μ˜ 선언문이 μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ μ΅œμƒλ‹¨μœΌλ‘œ λŒμ–΄μ˜¬λ €μ§„ κ²ƒμ²˜λŸΌ μ§„ν–‰λ˜λŠ” ν˜„μƒμ„ λ§ν•œλ‹€. (μ‹€μ œλ‘œ 물리적으둜 λ³€μˆ˜μ˜ 선언문이 μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ μ΅œμƒλ‹¨μœΌλ‘œ λŒμ–΄ μ˜¬λ €μ§€μ§€ μ•ŠλŠ”λ‹€.)μ΄λŠ” λ³€μˆ˜ 뿐만 μ•„λ‹ˆλΌ ν•¨μˆ˜μ—λ„ μ μš©λœλ‹€.

μžλ°”μŠ€ν¬λ¦½νŠΈκ°€ μ†ŒμŠ€μ½”λ“œλ₯Ό 평가할 λ•Œ, μ†ŒμŠ€μ½”λ“œμ˜ μ„ μ–Έλ¬Έλ§Œ μ‹€ν–‰ν•΄ μ‹λ³„μžλ“€μ΄ μœ„μ—μ„œλΆ€ν„° μ•„λž˜μ˜ μˆœμ„œλŒ€λ‘œ LexicalEnvironment의 EnvironmentRecord에 ν‚€(key)둜 λ“±λ‘λœλ‹€. μ΄λ ‡κ²Œ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ λ§Œλ“€μ–΄μ§„ μ‹œμ κΉŒμ§€λŠ” 값이 ν• λ‹Ήλ˜μ–΄μžˆμ§€μ•Šλ‹€. (varν‚€μ›Œλ“œλ‘œ λ§Œλ“  λ³€μˆ˜λŠ” μ„ μ–Έ, μ΄ˆκΈ°ν™”λ‹¨κ³„κ°€ ν•œ λ²ˆμ— μ‹€ν–‰λ˜μ–΄ undefined둜 μ•”λ¬΅μ μœΌλ‘œ μ΄ˆκΈ°ν™”λœλ‹€. 이 λ‚΄μš©μ΄ μƒˆλ‘­κ²Œ λŠκ»΄μ§„λ‹€λ©΄ μ•„λž˜ 글을 읽고 와라.)

➑️ μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ λ³€μˆ˜μ™€ 데이터 νƒ€μž…

κ·ΈλŸ¬κ³ λ‚˜μ„œ μ†ŒμŠ€μ½”λ“œ 평가가 μ™„λ£Œλ˜κ³  μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ 객체가 λ§Œλ“€μ–΄μ Έ 콜 μŠ€νƒμ— μŒ“μ΄λ©΄ 선언문을 μ œμ™Έν•œ μ†ŒμŠ€μ½”λ“œμ˜ 싀행이 μ‹œμž‘λ˜λ©΄μ„œ μ‹λ³„μžμ— 값을 ν• λ‹Ήν•˜λŠ” μ½”λ“œλ₯Ό λ§Œλ‚˜λ©΄ LexicalEnvironment의 EnvironmentRecord에 ν‚€(key)둜 μ €μž₯된 μ‹λ³„μžμ— κ°’(value)이 ν• λ‹Ήλœλ‹€.

λ³€μˆ˜ ν˜Έμ΄μŠ€νŒ…

μœ„μ—μ„œ μ‚΄νŽ΄λ³Έ λ³€μˆ˜ ν˜Έμ΄μŠ€νŒ…μ΄ μΌμ–΄λ‚˜λŠ” 과정을 μ½”λ“œλ‘œ μ‚΄νŽ΄λ³΄μž. λ³€μˆ˜ ν˜Έμ΄μŠ€νŒ…μ€ varν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ λ³€μˆ˜μ™€ let, const둜 μ„ μ–Έν•œ λ³€μˆ˜κ°€ λ‹€λ₯΄κ²Œ λ‚˜νƒ€λ‚˜λ―€λ‘œ λ”°λ‘œ λ”°λ‘œ μ‚΄νŽ΄λ³΄κ² λ‹€.

console.log(num); // undefined

var num = 10; 

console.log(num); // 10
  1. μ „μ—­ 객체 생성
    λ‚˜μ€‘μ— λ‹€λ£¨κ²Œ λ˜κ² μ§€λ§Œ μ†ŒμŠ€μ½”λ“œκ°€ ν‰κ°€λ˜κΈ° 이전에 전역객체가 μ‹€ν–‰λœλ‹€.

  2. μ†ŒμŠ€μ½”λ“œ 평가
    μ†ŒμŠ€μ½”λ“œ 평가 κ³Όμ •μ—μ„œ μ„ μ–Έλ¬Έλ§Œ λ¨Όμ € μ‹€ν–‰ν•œλ‹€. 이 λ•Œ μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ LexicalEnvironment의 EnvironmentRecord의 DeclarativeEnvironmentRecord에 μ‹λ³„μž num이 ν‚€λ‘œ λ“±λ‘λœλ‹€. var ν‚€μ›Œλ“œλ‘œ μƒμ„±λ˜μ—ˆκΈ° λ•Œλ¬Έμ— μ„ μ–Έκ³Ό μ΄ˆκΈ°ν™”κ°€ λ™μ‹œμ— 이루어져 κ°’μœΌλ‘œ undefinedκ°€ ν• λ‹Ήλœλ‹€. (this바인딩과 OuterEnvironmentReference 섀정은 ν˜Έμ΄μŠ€νŒ…κ³Ό 연관이 μ—†μ–΄ μƒλž΅ν–ˆλ‹€.)

  3. 첫번째 'console.log'
    μ†ŒμŠ€μ½”λ“œ 평가가 λλ‚˜λ©΄ 선언문을 μ œμ™Έν•œ μ†ŒμŠ€μ½”λ“œκ°€ μ‹€ν–‰λœλ‹€. μ²«λ²ˆμ§Έμ€„μ˜ console.log(num)λ₯Ό λ§Œλ‚˜λ©΄ (사싀 console μ‹λ³„μžλ„ κ²€μƒ‰ν•˜κ³  μ΄λŸ¬μ €λŸ¬ν•œ 과정을 더 κ±°μΉ˜μ§€λ§Œ μƒλž΅ν•˜κ² λ‹€.) numμ‹λ³„μžλ₯Ό ν˜„μž¬ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ (μœ„ μ½”λ“œμ—μ„œλŠ” μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ) LexicalEnvironmentμ—μ„œ λ“±λ‘λ˜μ–΄ μžˆλŠ”μ§€ μ°ΎλŠ”λ‹€. μ§€κΈˆμ€ λ“±λ‘λ˜μ–΄μžˆκΈ° λ•Œλ¬Έμ— num의 값인 undefinedλ₯Ό 좜λ ₯ν•œλ‹€.

  4. var num = 10;
    μ„ μ–Έλ¬Έ 뢀뢄을 μ œμ™Έν•˜κ³  'num = 10'만 μ‹€ν–‰ν•΄ λ“±λ‘λœ num의 값을 10으둜 μž¬ν• λ‹Ήν•œλ‹€.

  5. λ‘λ²ˆμ§Έ 'console.log'
    또 λ‹€μ‹œ numμ‹λ³„μžλ₯Ό ν˜„μž¬ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ (μœ„ μ½”λ“œμ—μ„œλŠ” μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ)의 LexicalEnvironmentμ—μ„œ λ“±λ‘λ˜μ–΄ μžˆλŠ”μ§€ μ°ΎλŠ”λ‹€. μ—­μ‹œλ‚˜ λ“±λ‘λ˜μ–΄μžˆκΈ° λ•Œλ¬Έμ— num의 값인 10을 좜λ ₯ν•œλ‹€.

μ΄λŸ¬ν•œ 과정을 κ²ͺμ–΄ λ³€μˆ˜ ν˜Έμ΄μŠ€νŒ…μ΄λΌλŠ” ν˜„μƒμ΄ μΌμ–΄λ‚œλ‹€. let, const ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ λ³€μˆ˜λŠ” μ–΄λ–»κ²Œ var ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ λ³€μˆ˜μ™€ λ‹€λ₯Έμ§€ μ‚΄νŽ΄λ³΄μž.

console.log(num); // Reference Error

var num = 10; 

console.log(num); // 10

letμ΄λ‚˜ const둜 μ„ μ–Έν•œ λ³€μˆ˜λŠ” varν‚€μ›Œλ“œμ™€ 달리 "μ„ μ–Έ"κ³Ό "μ΄ˆκΈ°ν™”"단계가 λΆ„λ¦¬λ˜μ–΄ μΌμ–΄λ‚˜κΈ° λ•Œλ¬Έμ— λŸ°νƒ€μž„μ— μ‹€ν–‰ 흐름이 λ³€μˆ˜ 선언문에 λ„λ‹¬ν•˜κΈ° μ „κΉŒμ§€ 아무 값도 λ³€μˆ˜κ°€ λ‹΄κ²¨μžˆμ§€ μ•Šμ€λ°, 이 λ•Œ λ³€μˆ˜μ— μ ‘κ·Όν•  수 μ—†κΈ° λ•Œλ¬Έμ— λ³€μˆ˜ 선언문에 λ„λ‹¬ν•˜κΈ° μ „κΉŒμ§€λ₯Ό μΌμ‹œμ  μ‚¬κ°μ§€λŒ€(Temporal Dead Zone) TDZ라고 λΆ€λ₯Έλ‹€.

이 λ•Œλ¬Έμ— 첫번째 console.logκ°€ 싀행될 λ•Œ μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ— λ“±λ‘λœ numμ—λŠ” 아직 값이 μ—†κΈ° λ•Œλ¬Έμ— num은 μΌμ‹œμ  μ‚¬κ°μ§€λŒ€μ— λΉ μ Έ μžˆλŠ” μƒνƒœμ΄λ‹€. κ·Έλž˜μ„œ Reference Errorκ°€ λ°œμƒν•œλ‹€.

즉, var ν‚€μ›Œλ“œλ‘œ λ³€μˆ˜λ₯Ό λ§Œλ“€λ˜ let, const ν‚€μ›Œλ“œλ‘œ λ³€μˆ˜λ₯Ό λ§Œλ“€λ˜ ν˜Έμ΄μŠ€νŒ…μ€ μΌμ–΄λ‚˜μ§€λ§Œ var ν‚€μ›Œλ“œλ‘œ λ§Œλ“  λ³€μˆ˜λŠ” 선언문에 λ„λ‹¬ν•˜κΈ° 전에 λ³€μˆ˜λ₯Ό μ°Έμ‘°ν•  수 μžˆμ§€λ§Œ, let, const ν‚€μ›Œλ“œλ‘œ λ§Œλ“  λ³€μˆ˜λŠ” 선언문에 λ„λ‹¬ν•˜κΈ° 전에 λ³€μˆ˜λ₯Ό μ°Έμ‘°ν•  수 μ—†λ‹€.

ν•¨μˆ˜ ν˜Έμ΄μŠ€νŒ…

ν•¨μˆ˜ ν˜Έμ΄μŠ€νŒ…μ€ "ν•¨μˆ˜ μ„ μ–Έλ¬Έ" λ°©μ‹μœΌλ‘œ μ •μ˜ν•œ ν•¨μˆ˜μ™€ "ν•¨μˆ˜ ν‘œν˜„μ‹" λ°©μ‹μœΌλ‘œ μ •μ˜ν•œ ν•¨μˆ˜κ°€ λ‹€λ₯΄κ²Œ μΌμ–΄λ‚˜λŠ”λ°, λ¨Όμ € λ³€μˆ˜μ— ν•¨μˆ˜λ₯Ό λ‹΄μ•„μ„œ ν•¨μˆ˜λ₯Ό μ„ μ–Έν•˜λŠ” ν•¨μˆ˜ ν‘œν˜„μ‹μ˜ ν˜Έμ΄μŠ€νŒ…μ€ μœ„μ—μ„œ μ‚΄νŽ΄λ³Έ λ³€μˆ˜ ν˜Έμ΄μŠ€νŒ…κ³Ό λ˜‘κ°™μ΄ λ°œμƒν•œλ‹€.

ν•¨μˆ˜ μ„ μ–Έλ¬ΈμœΌλ‘œ μ„ μ–Έν•œ ν•¨μˆ˜λŠ” ν•¨μˆ˜ 전체가 ν˜Έμ΄μŠ€νŒ…λ˜κΈ° λ•Œλ¬Έμ— λŸ°νƒ€μž„μ— μ‹€ν–‰ 흐름이 ν•¨μˆ˜μ˜ μ„ μ–Έμ˜ 이전에도 ν•¨μˆ˜λ₯Ό μ°Έμ‘°ν•  수 μžˆλ‹€. κ·ΈλŸ¬λ‚˜ μ΄λŠ” λ§Žμ€ ν˜Όλž€μ„ λ°œμƒμ‹œν‚¬ 수 있기 λ•Œλ¬Έμ— ν•¨μˆ˜ ν‘œν˜„μ‹ λ°©μ‹μœΌλ‘œ ν•¨μˆ˜λ₯Ό μ„ μ–Έν•˜λŠ” 것이 μ’‹λ‹€.

ν•¨μˆ˜ μ„ μ–Έλ¬Έ 방식은 λŸ°νƒ€μž„ 이전, ν•¨μˆ˜ μ •μ˜κ°€ ν‰κ°€λ˜λŠ” μ‹œμ μ— ν•¨μˆ˜ 객체가 μƒμ„±λœλ‹€.
ν•¨μˆ˜ ν‘œν˜„μ‹ 방식은 λŸ°νƒ€μž„ 도쀑, λ³€μˆ˜μ— ν•¨μˆ˜ μ •μ˜κ°€ ν‰κ°€λ˜μ–΄ ν• λ‹Ήλ˜λŠ” μ‹œμ μ— ν•¨μˆ˜ 객체가 μƒμ„±λœλ‹€.


πŸ₯· OuterEnvironmentReference와 λ³€μˆ˜ 은닉화

μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ μŠ€μ½”ν”„μ—μ„œ μ‚΄νŽ΄λ΄€λ“―μ΄ μŠ€μ½”ν”„ 체인은 ν•˜μœ„ μŠ€μ½”ν”„μ—μ„œ μƒμœ„ μŠ€μ½”ν”„λ‘œ 단방ν–₯으둜만 이동할 수 μžˆλ‹€κ³  ν–ˆλ‹€. OuterEnvironmentReferenceλ₯Ό 톡해 단방ν–₯ μ—°κ²°λ¦¬μŠ€νŠΈλ‘œ κ΅¬ν˜„λœ μŠ€μ½”ν”„ 체인을 μ˜ˆμ‹œμ½”λ“œλ‘œ μ‚΄νŽ΄λ³΄λ©΄μ„œ λ³€μˆ˜ 은닉화에 λŒ€ν•΄μ„œλ„ μ‚΄νŽ΄λ³΄μž.

let name = 'Harry';

function inner() {
  let name = 'Hyeok';
  
  console.log(name);
}

inner();
console.log(name);
  1. μ „μ—­ μ½”λ“œ 평가
    평가 이전에 μ „μ—­ 객체가 μƒμ„±λ˜κ³ , 이후 μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ μƒμ„±λœλ‹€. 첫 μ€„μ—μ„œ λ³€μˆ˜ 선언문을 λ§Œλ‚˜ LexicalEnvironment의 EnvironmentRecord의 DeclarativeEnvironmentRecord에 name이 λ“±λ‘λœλ‹€. 이후 ν•¨μˆ˜ 선언문을 λ§Œλ‚˜ ObjectEnvironmentRecord에 inner ν•¨μˆ˜ μžμ²΄κ°€ λ“±λ‘λœλ‹€. 이후 OuterEnvironmentReference에 μƒμœ„ μŠ€μ½”ν”„λ₯Ό κ°€λ¦¬μΌœμ•Ό ν•˜λ‚˜, μ „μ—­ μ½”λ“œμ˜ μƒμœ„ μŠ€μ½”ν”„λŠ” μ—†μœΌλ―€λ‘œ null이 ν• λ‹Ήλœλ‹€. (this 바인딩 과정은 μƒλž΅ν–ˆλ‹€.)

  2. μ „μ—­ μ½”λ“œ μ‹€ν–‰
    μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ 콜 μŠ€νƒμ— μŒ“μ΄λ©΄ μ „μ—­ μ½”λ“œκ°€ μ‹€ν–‰λœλ‹€. 첫 μ€„μ—μ„œ name에 Harryκ°€ ν• λ‹Ήλ˜κ³ , inner()λ₯Ό λ§Œλ‚˜λ©΄ innerμ½”λ“œλ₯Ό ν‰κ°€ν•œλ‹€.

  3. inner μ½”λ“œ 평가
    첫 μ€„μ—μ„œ λ³€μˆ˜ 선언문을 λ§Œλ‚˜ LexicalEnvironment의 EnvironmentRecord에 name이 λ“±λ‘λœλ‹€. OuterEnvironmentReference에 μƒμœ„ μŠ€μ½”ν”„μΈ μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ LexicalEnvironmentλ₯Ό ν• λ‹Ήν•œλ‹€. (μ—­μ‹œ this 바인딩 과정은 μƒλž΅ν–ˆλ‹€.)

  4. inner μ½”λ“œ μ‹€ν–‰
    inner μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ 콜 μŠ€νƒμ— μŒ“μ΄λ©΄ μ „μ—­ μ½”λ“œμ˜ 싀행이 μ€‘μ§€λ˜κ³  inner μ½”λ“œκ°€ μ‹€ν–‰λœλ‹€. 첫 μ€„μ—μ„œ ν˜„μž¬ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ LexicalEnvironment의 EnvironmentRecord에 λ“±λ‘λœ name에 Hyeok이 ν• λ‹Ήλ˜κ³  console.log(name)μ—μ„œ name이 ν˜„μž¬ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ LexicalEnvironmentμ—μ„œ λ“±λ‘λ˜μ–΄ μžˆλŠ”μ§€ μ°ΎλŠ”λ‹€. μ§€κΈˆμ€ λ“±λ‘λ˜μ–΄μžˆκΈ° λ•Œλ¬Έμ— name의 값인 Hyeok을 좜λ ₯ν•œλ‹€.

일단 μ—¬κΈ°κΉŒμ§€λ§Œ μ•Œμ•„λ³΄λ„λ‘ ν•˜κ² λ‹€. inner의 console.log(name)μ—μ„œ Hyeok이 좜λ ₯λ˜λŠ” μ΄μœ λŠ” inner ν•¨μˆ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ—μ„œ name이 λ°œκ²¬λ˜μ—ˆκΈ° λ•Œλ¬ΈμΈλ° 이둜 인해 μ „μ—­μ—μ„œ μ„ μ–Έν•œ λ™μΌν•œ μ΄λ¦„μ˜ name λ³€μˆ˜μ—λŠ” μ ‘κ·Όν•  μˆ˜κ°€ μ—†μ—ˆλ‹€.

이λ₯Ό λ³€μˆ˜ 은닉화(variable shadowing)이라고 ν•œλ‹€.


🧐 정리

  • μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλž€ μ†ŒμŠ€μ½”λ“œλ₯Ό μ‹€ν–‰ν•  λ•Œ μ œκ³΅ν•  ν™˜κ²½ 정보λ₯Ό λͺ¨μ•„놓은 객체이닀.
  • 콜 μŠ€νƒμ€ μ†ŒμŠ€μ½”λ“œμ˜ μ‹€ν–‰ μˆœμ„œλ₯Ό κ΄€λ¦¬ν•œλ‹€.
  • μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλŠ” μ‹λ³„μžμ˜ 등둝과 값을 κ΄€λ¦¬ν•˜κ³ , μŠ€μ½”ν”„ 체인을 κ΄€λ¦¬ν•œλ‹€.
  • EnvironmentRecord의 μ‹λ³„μž λ“±λ‘κ³Όμ •μ—μ„œ ν˜Έμ΄μŠ€νŒ…μ΄ λ°œμƒν•œλ‹€.
  • OuterEnvironmentReference의 μŠ€μ½”ν”„ 체인 κ΅¬ν˜„λ°©μ‹μœΌλ‘œ 인해 λ³€μˆ˜ 은닉화가 λ°œμƒν•œλ‹€.

πŸ“– 참고자료

  • μ½”μ–΄ μžλ°”μŠ€ν¬λ¦½νŠΈ

      1. μ‹€ν–‰μ»¨ν…μŠ€νŠΈ (36p~63p)
  • λͺ¨λ˜ μžλ°”μŠ€ν¬λ¦½νŠΈ Deep Dive

      1. μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ (359p~386p)
  • μš°ν…Œμ½” ν”„λ‘ νŠΈμ—”λ“œJS 레벨1 - 2022

    • μžλ™μ°¨ κ²½μ£Ό πŸ”¬ Execution Context & Scope
profile
μš°μ•„ν•œν…Œν¬μ½”μŠ€ 4κΈ° μ›Ή ν”„λ‘ νŠΈμ—”λ“œ

2개의 λŒ“κΈ€

comment-user-thumbnail
2022λ…„ 3μ›” 4일

good

λ‹΅κΈ€ 달기
comment-user-thumbnail
2022λ…„ 10μ›” 31일

μ΅œμ‹  ECMAScriptμ—μ„œλŠ” ν‹€λ¦° κΈ€μž…λ‹ˆλ‹€

λ‹΅κΈ€ 달기