λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

JavaScript

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

μ‹€ν–‰μ»¨ν…μŠ€νŠΈλ₯Ό κ³΅λΆ€ν•˜λ©΄μ„œ μ‹€ν–‰μ»¨ν…μŠ€νŠΈ, ν™˜κ²½λ ˆμ½”λ“œ, λ ‰μ‹œμ»¬ν™˜κ²½ λ“±μ˜ 관계가 ꡉμž₯히 λ³΅μž‘ν•˜κ²Œ μ–½ν˜€μžˆμŒμ„ μ•Œκ²Œ λ˜μ—ˆλ‹€. κ·ΈλŸ¬λ‹€ 문득 ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ˜ κ²½μš°μ— μ‹€ν–‰μ»¨ν…μŠ€νŠΈλŠ” μ–΄λ–€μ‹μœΌλ‘œ λ™μž‘ν•˜λŠ”μ§€κ°€ κΆκΈˆν•΄μ‘Œλ‹€. μš°μ„  μ‹€ν–‰μ»¨ν…μŠ€νŠΈλ₯Ό κ³΅λΆ€ν•˜λ©΄μ„œ μ•Œκ²Œ 된 λ‚΄μš©λ“€μ„ 정리해 보렀고 ν•œλ‹€.

 

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

μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ λ™μž‘μ›λ¦¬λ₯Ό λ‹΄λŠ” 핡심 κ°œλ…μœΌλ‘œ κ°„λ‹¨νžˆ λ§ν•΄μ„œ μ½”λ“œμ˜μ‹€ν–‰ν™˜κ²½μ΄λΌκ³  λ³Ό 수 μžˆλ‹€.

μ‹€ν–‰μ»¨ν…μŠ€νŠΈλ₯Ό μƒμ„±ν•˜λŠ” μ½”λ“œμ—λŠ” 넀가지가 μ‘΄μž¬ν•œλ‹€.

1. μ „μ—­ μ½”λ“œ: 전역에 μ‘΄μž¬ν•˜λŠ” μ½”λ“œ
2. ν•¨μˆ˜ μ½”λ“œ: ν•¨μˆ˜ 내뢀에 μ‘΄μž¬ν•˜λŠ” μ½”λ“œ
3. eval μ½”λ“œ: eval ν•¨μˆ˜μ˜ 인수둜 μ „λ‹¬λ˜μ–΄ μ‹€ν–‰λ˜λŠ” μ½”λ“œ
4. λͺ¨λ“ˆ μ½”λ“œ: λͺ¨λ“ˆ 내뢀에 μ‘΄μž¬ν•˜λŠ” μ½”λ“œ

κ°€μž₯ λ¨Όμ € μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ μŠ€ν…μ— μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ μƒμ„±λ˜κ³ , μ „μ—­ λ ‰μ‹œμ»¬ν™˜κ²½ μƒμ„±, μ „μ—­ ν™˜κ²½ λ ˆμ½”λ“œ μƒμ„±, κ°μ²΄ ν™˜κ²½ λ ˆμ½”λ“œ, μ„ μ–Έμ  ν™˜κ²½ λ ˆμ½”λ“œκ°€ μƒμ„±λœλ‹€.

객체 ν™˜κ²½ λ ˆμ½”λ“œλŠ” BindingObjectλΌλŠ” 객체와 μ—°κ²°λ˜λŠ”λ° μ΄λŠ” μ „μ—­ 객체이닀.

 

λ¨Όμ € μ½”λ“œκ°€ 싀행이 되면 μ „μ—­μ½”λ“œλ₯Ό ν‰κ°€ν•˜λŠ” 과정을 κ±°μΉœλ‹€.

ν‰κ°€κ³Όμ •μ—μ„œλŠ” μ„ μ–Έλ¬Έλ“€λ§Œ λ¨Όμ € 싀행이 λ˜λŠ”λ° ν•΄λ‹Ή μ½”λ“œλ₯Ό κΈ°μ€€μœΌλ‘œ var ν‚€μ›Œλ“œλ‘œ μ„ μ–Έλœ μ „μ—­ λ³€μˆ˜μ™€ foo ν•¨μˆ˜ 선언문이 λ¨Όμ € ν‰κ°€λœλ‹€. λ˜ν•œ, μ„ μ–Έλœ λ³€μˆ˜ 및 ν•¨μˆ˜λŠ” μ „μ—­ 객체의 ν”„λ‘œνΌν‹°μ™€ λ©”μ„œλ“œκ°€ λœλ‹€.(window 객체의 x, foo)

 const와 let ν‚€μ›Œλ“œλ‘œ μ„ μ–Έλœ λ³€μˆ˜λŠ” 선언적 ν™˜κ²½ λ ˆμ½”λ“œμ— λ“±λ‘λœλ‹€. μ΄λ•Œ 아직 할당이 λ˜μ§€ μ•Šκ³ , ν˜Έμ΄μŠ€νŒ…μ΄ λ™μž‘ν•˜μ§€ μ•ŠλŠ” κ²ƒμ²˜λŸΌ λ™μž‘ν•˜κΈ° λ•Œλ¬Έμ— μ•Œ 수 μ—†λŠ” 값이 μ‘΄μž¬ν•˜κ²Œ λœλ‹€.

 

 

κ°„λ‹¨ν•œ μ½”λ“œλ₯Ό κΈ°μ€€μœΌλ‘œ 그림을 κ·Έλ¦¬λ©΄μ„œ μ„€λͺ…을 μΆ”κ°€ν•˜λ €κ³  ν•œλ‹€.

var x = 1;
const x2 = 2;

function foo() {
  const x3 = 3;
  console.log(x3);
}

foo();

그리고 thisκ°€ λ°”μΈλ”©λ˜λŠ”λ° μ „μ—­ λ ‰μ‹œμ»¬ ν™˜κ²½μ˜ [[GlobalThisValue]] λ‚΄λΆ€μŠ¬λ‘―μ— thisκ°€ λ°”μΈλ”©λœλ‹€. μ „μ—­ μ½”λ“œμ—μ„œμ˜ thisλŠ” μ „μ—­ 객체λ₯Ό κ°€λ₯΄ν‚€κΈ° λ•Œλ¬Έμ— 전역객체 windowκ°€ 바인딩 λœλ‹€.

 

μ™ΈλΆ€ λ ‰μ‹œμ»¬ ν™˜κ²½ μ°Έμ‘°λŠ” ν˜„μž¬ 평가쀑인 μ†ŒμŠ€ μ½”λ“œλ₯Ό ν¬ν•¨ν•˜λŠ” μ™ΈλΆ€ μ†ŒμŠ€ μ½”λ“œμ˜ λ ‰μ‹œμ»¬ ν™˜κ²½μΈ μƒμœ„ μŠ€μ½”ν”„λ₯Ό κ°€λ₯΄ν‚€λŠ”데 μ „μ—­μ˜ 경우 null이 ν• λ‹Ήλœλ‹€.

 

μ „μ—­ μ½”λ“œ 평가 이후 μ „μ—­ μ½”λ“œκ°€ 싀행이 되게 λ˜λŠ”λ° μ΄λ•Œ μ„ μ–Έλ§Œ λ˜μ—ˆλ˜ λ³€μˆ˜ 값듀에 값이 할당이 되게 λœλ‹€.

ν•¨μˆ˜μ½”λ“œμ˜ 경우 ν•¨μˆ˜κ°€ ν˜ΈμΆœλ λ•Œ ν•¨μˆ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ 생성이 λœλ‹€.

μ½”λ“œμ˜ λ§ˆμ§€λ§‰ 뢀뢄에 fooν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ”λ° μ΄λ•Œ μ „μ—­ μ½”λ“œμ˜ 싀행을 μΌμ‹œ μ€‘λ‹¨ν•˜κ³  fooν•¨μˆ˜λ‘œ μ œμ–΄κΆŒμ΄ μ΄λ™ν•œλ‹€.(μ΄λ•Œ ν•¨μˆ˜ λ‚΄λΆ€ μ½”λ“œκ°€ ν‰κ°€λœλ‹€.) ν•¨μˆ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ 생성이 되고, ν•¨μˆ˜ λ ‰μ‹œμ»¬ ν™˜κ²½ μƒμ„±, ν•¨μˆ˜ ν™˜κ²½ λ ˆμ½”λ“œκ°€ μƒμ„±λœλ‹€

 

ν•¨μˆ˜λ„ λ§ˆμ°¬κ°€μ§€λ‘œ ν‰κ°€λ λ•Œ, 선언문듀이 λ¨Όμ € 등둝이 λœλ‹€.

λ”°λΌμ„œ const x3 = 3;의 const ν‚€μ›Œλ“œλ‘œ μ„ μ–Έλœ x3(const x3)κ°€ ν•¨μˆ˜ ν™˜κ²½ λ ˆμ½”λ“œμ— 등둝이 λœλ‹€.

ν•¨μˆ˜μ˜ λ§€κ°œλ³€μˆ˜, argument 객체, ν•¨μˆ˜ λͺΈμ²΄ λ‚΄λΆ€μ—μ„œ μ„ μ–Έλœ μ‹λ³„μžλ“€μ΄ ν•¨μˆ˜ ν™˜κ²½ λ ˆμ½”λ“œμ— 등둝이 λœλ‹€.

이후 thisκ°€ 바인딩 λ˜λŠ”λ° μ΄λ•Œ foo ν•¨μˆ˜λŠ” μΌλ°˜ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœλ˜μ—ˆκΈ° λ•Œλ¬Έμ— thisλŠ” μ „μ—­ 객체가 λœλ‹€.

ν•¨μˆ˜μ˜ μ™ΈλΆ€ λ ‰μ‹œμ»¬ ν™˜κ²½μ— λŒ€ν•œ μ°Έμ‘°λŠ” μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진이 ν•¨μˆ˜ μ •μ˜λ₯Ό ν‰κ°€ν•˜κ³  ν•¨μˆ˜ 객체λ₯Ό μƒμ„±ν• λ•Œ μ‹€ν–‰μ€‘인 μ»¨ν…μŠ€νŠΈμ˜ λ ‰μ‹œμ»¬ ν™˜κ²½μ„ ν•¨μˆ˜ 객체의 λ‚΄λΆ€μŠ¬λ‘― [[Environment]]에 μ €μž₯ν•œλ‹€.

 

이후 ν•¨μˆ˜ λ ‰μ‹œμ»¬ ν™˜κ²½μ— μžˆλŠ” μ™ΈλΆ€ λ ‰μ‹œμ»¬ν™˜κ²½μ— λŒ€ν•œ μ°Έμ‘°λŠ” 이 ν•¨μˆ˜μ˜ λ‚΄λΆ€μŠ¬λ‘― [[Environment]]λ₯Ό μ°Έμ‘°ν•œλ‹€. λ”°λΌμ„œ μœ„ μ½”λ“œλ₯Ό κΈ°μ€€μœΌλ‘œ foo ν•¨μˆ˜μ˜ μ™ΈλΆ€ λ ‰μ‹œμ»¬ ν™˜κ²½μ— λŒ€ν•œ μ°Έμ‘°λŠ” μ „μ—­ λ ‰μ‹œμ»¬ ν™˜κ²½μ„ κ°€λ₯΄ν‚¨λ‹€.

ν•¨μˆ˜ λ‚΄λΆ€ 평가 이후 ν•¨μˆ˜ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λ©΄μ„œ ν•¨μˆ˜ ν™˜κ²½ λ ˆμ½”λ“œμ— μ‘΄μž¬ν•˜λŠ” λ³€μˆ˜ x3μ—λŠ” 3이 ν• λ‹Ήλ˜κ³  console.log(x3)κ°€ μ‹€ν–‰λ˜λŠ”λ° μ΄λ•Œ console의 log λ©”μ„œλ“œλ₯Ό 호좜 즉, ν•¨μˆ˜ 호좜이기 λ•Œλ¬Έμ— 또 λ‹€μ‹œ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ λ§Œλ“€μ–΄μ§„λ‹€.

μ΄λ•Œ `console` κ°μ²΄λŠ” window 객체가 λ§Œλ“€μ–΄μ§ˆλ•Œ 내뢀에 μ‘΄μž¬ν•˜κΈ° λ•Œλ¬Έμ— μ „μ—­ 객체(window)μ—μ„œ `console`을 μ°Ύμ•„ `log` ν•¨μˆ˜λ₯Ό ν‰κ°€ν•˜λŠ” 과정을 κ±°μΉœλ‹€.

λ‚΄λΆ€μ μœΌλ‘œ 인수λ₯Ό λ°›κΈ° λ•Œλ¬Έμ— ν•΄λ‹Ή μΈμˆ˜κ°€ log ν•¨μˆ˜ ν™˜κ²½ λ ˆμ½”λ“œμ— λ“±λ‘λ˜κΈ° 전에 log ν•¨μˆ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ μƒμ„±λ˜κ³ , ν•¨μˆ˜ λ ‰μŠ€μ»¬ ν™˜κ²½, ν•¨μˆ˜ ν™˜κ²½ λ ˆμ½”λ“œλ“€μ΄ 생성이 되고 선언문듀이 ν•¨μˆ˜ ν™˜κ²½ λ ˆμ½”λ“œμ— 등둝이 λœλ‹€.

(λ‚΄λΆ€μ μœΌλ‘œ console.log둜 찍을 λ³€μˆ˜λ₯Ό xxxλΌλŠ” λ³€μˆ˜λΌκ³  가정함 - argumentλ₯Ό μ΄μš©ν•΄μ„œ 좜λ ₯할지도 λͺ¨λ₯΄κ² λ‹€λŠ” 생각을 ν•œλ‹€!)

log ν•¨μˆ˜ λ ‰μ‹œμ»¬ ν™˜κ²½μ˜ [[ThisValue]]μ—λŠ” 전역객체 window의 console 객체가 바인딩 λœλ‹€.

μ™ΈλΆ€ λ ‰μ‹œμ»¬ ν™˜κ²½μ— λŒ€ν•œ μ°Έμ‘°μ—λŠ” ν˜„μž¬ 싀행쀑인 μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ foo ν•¨μˆ˜μ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ μ΄λ―€λ‘œ fooν•¨μˆ˜μ˜ λ ‰μ‹œμ»¬ ν™˜κ²½μ„ κ°€λ₯΄ν‚€κ²Œ λœλ‹€.

log ν•¨μˆ˜μ˜ 평가가 μ’…λ£Œλ˜κ³  μ‹€ν–‰λ˜λ©΄μ„œ xxxμ—λŠ” 인수둜 λ„£μ–΄μ€€ 3이 할당이 되고 λ‚΄λΆ€ λ™μž‘μœΌλ‘œ 인해 console에 3이라고 찍히게 λœλ‹€.

logν•¨μˆ˜κ°€ μ’…λ£Œκ°€ 되면 log ν•¨μˆ˜μ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ μŠ€ν…μ—μ„œ μ œκ±°λœλ‹€. μ΄λ•Œ λ ‰μ‹œμ»¬ ν™˜κ²½μ΄ λ°”λ‘œ μ‚¬λΌμ§€μ§€λŠ” μ•ŠλŠ”λ° μ΄λŠ” ν΄λ‘œμ €μ™€ μ—°κ΄€λœλ‹€.

 

log ν•¨μˆ˜μ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ 제거되고, foo ν•¨μˆ˜λ„ μ’…λ£Œλ˜λ―€λ‘œ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ μŠ€ν…μ—μ„œ 제거, μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλ„ λ§ˆμ°¬κ°€μ§€λ‘œ μ œκ±°λ˜λ―€λ‘œ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ μŠ€ν…μ—λŠ” 아무것도 남지 μ•Šκ²Œ 되고 μ΄λ•Œ μ½”λ“œκ°€ μ’…λ£Œλœλ‹€.

 

κ²°κ΅­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ μŠ€ν…μ—μ„œ κ°€μž₯ 상단에 μ‘΄μž¬ν•˜λŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ ν˜„μž¬ 싀행쀑인 μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ΄κ³ , μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ μ‘΄μž¬ν• λ•Œ μ½”λ“œκ°€ 싀행됨을 μ•Œ 수 μžˆλ‹€.

 

이런 과정듀을 κ±°μΉ˜λ©΄μ„œ μžλ°”μŠ€ν¬λ¦½νŠΈ μ½”λ“œκ°€ 싀행이 λ˜λŠ”λ° κ·Έλ ‡λ‹€λ©΄ ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ˜ 경우 λ°˜λ³΅ν•΄μ„œ μž¬κ·€ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ”λ° μ΄λ•ŒλŠ” μ–΄λ–»κ²Œ λ˜λŠ”μ§€ μ°Ύμ•„λ΄€λ‹€.

 

ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ€ 0κ³Ό 1둜 μ‹œμž‘ν•΄μ„œ λ‹€μŒ ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ˜ μˆ˜λŠ” μ•žμ˜ 두 수λ₯Ό λ”ν•œ 값이 λœλ‹€.

κ°„λ‹¨ν•˜κ²Œ F둜 λ‚˜νƒ€λ‚΄μ„œ 4λ‹¨κ³„μ˜ ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄λ‘œ 그림을 그렀보면 λ‹€μŒκ³Ό κ°™λ‹€.

μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό μ΄μš©ν•΄μ„œ ν”Όλ³΄λ‚˜μΉ˜λ₯Ό κ°„λ‹¨ν•˜κ²Œ κ΅¬ν˜„ν–ˆμ„λ•ŒλŠ” λ‹€μŒκ³Ό κ°™λ‹€.

function fibonacci(n) {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

console.log(fibonacci(10)); // 3

μœ„ μ½”λ“œμ— ifλ¬Έκ³Ό debuggerλ₯Ό μ΄μš©ν•΄μ„œ ν”Όλ³΄λ‚˜μΉ˜ ν•¨μˆ˜κ°€ 크둬 λΈŒλΌμš°μ €μ—μ„œ μ‹€ν–‰λ λ•Œ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ(call stack)κ°€ μ–Όλ§ˆλ‚˜ μŒ“μ΄λŠ”μ§€ ν™•μΈν•΄λ³΄μ•˜λ‹€.

function fibonacci(n) {
  if (n <= 1) return n;
  if (n === 2) debugger;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

console.log(fibonacci(4));

4번째 수λ₯Ό μ°Ύμ„λ•Œ n이 2μΌλ•Œλ₯Ό 확인해보면

μ΄μ–΄μ„œ 10번째 수λ₯Ό μ°Ύμ„λ•Œ n이 2μΌλ•Œλ₯Ό 확인해보면

ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄ μ½”λ“œμ—μ„œ λ¨Όμ € μ „μ—­ μ½”λ“œκ°€ 평가가 λ˜λ©΄μ„œ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ μŠ€ν…μ— μ „μ—­ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ, μ „μ—­ λ ‰μ‹œμ»¬ν™˜κ²½, μ „μ—­ ν™˜κ²½ λ ˆμ½”λ“œ, 객체 ν™˜κ²½ λ ˆμ½”λ“œ, 선언적 ν™˜κ²½ λ ˆμ½”λ“œκ°€ μƒμ„±λ˜κ³ , μ „μ—­ 객체(window)의 λ©”μ„œλ“œλ‘œ fibonacci ν•¨μˆ˜κ°€ λ“±λ‘λœλ‹€. λ˜ν•œ this 바인딩은 전역객체가, μ™ΈλΆ€ λ ‰μ‹œμ»¬ ν™˜κ²½μ— λŒ€ν•œ μ°Έμ‘°μ—λŠ” null이 할당될 것이닀. 이후 ν”Όλ³΄λ‚˜μΉ˜ ν•¨μˆ˜κ°€ 호좜이 λ˜λ©΄μ„œ ν”Όλ³΄λ‚˜μΉ˜ ν•¨μˆ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ λ§Œλ“€μ–΄μ§€κ³  λ‚΄λΆ€μ μœΌλ‘œ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ©΄μ„œ λ°˜ν™˜ν•œλ‹€.

 

n이 2인 κ²½μš°μ— debugger을 ν•˜λ―€λ‘œ λ‹€μŒ κ·Έλ¦Όκ³Ό 같이 ν˜ΈμΆœλœλ‹€.

 

F(4), F(3), F(2) μˆœμ„œλ‘œ 호좜이 λœλ‹€. λ”°λΌμ„œ κ²°κ΅­ μ‹€ν–‰μ»¨ν…μŠ€νŠΈλŠ” λ‹€μŒκ³Ό 같이 κ΅¬μ„±λœλ‹€.

(F(4), F(3), F(2) μˆœμ„œλ‘œ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ μŠ€ν…μ— 각각의 μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ μƒμ„±λœλ‹€.)

 

μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλ₯Ό 그림으둜 κ·Έλ¦¬λ©΄μ„œ 곡뢀λ₯Ό ν•˜λ‹ˆ 보닀 μ‰½κ²Œ μ ‘κ·Όν•  수 μžˆμ—ˆλ‹€κ³  μƒκ°ν•œλ‹€. 아직도 ꡉμž₯히 μ–΄λ €μš΄ κ°œλ…μ΄μ§€λ§Œ μŠ€μ½”ν”„, ν΄λ‘œμ € λ“± λ§Žμ€ κ°œλ…λ“€μ΄ μ—°κ΄€λ˜μ–΄ 있기 λ•Œλ¬Έμ— 이상함을 λŠλ‚„λ•Œ 그림을 κ·Έλ €λ³΄λ©΄μ„œ 잘λͺ»λœ 뢀뢄을 μ°Ύμ•„κ°€λŠ” 것도 쒋은 λ°©λ²•μ΄λΌλŠ” 생각이 λ“€μ—ˆλ‹€