πŸ—ν˜Έμ΄μŠ€νŒ…μ— λŒ€ν•΄ (Hoisting)

πŸ—let ν‚€μ›Œλ“œμ™€ var ν‚€μ›Œλ“œμ˜ 차이

과거의 λ‚΄κ°€ μž‘μ„±ν•œ λΈ”λ‘œκ·Έλ₯Ό 톡해 μž¬λ³΅μŠ΅μ„ 진행할 수 μžˆμ—ˆλ‹€.

https://dev-seolleung2.netlify.app/development/Scope/

λ‚΄ λΈ”λ‘œκ·Έ λ‚΄μš©μ„ 쑰금 더 μš”μ•½ν•΄ λ³΄μ•˜λ‹€.

μŠ€μ½”ν”„λŠ” λ³€μˆ˜ μ ‘κ·Ό κ·œμΉ™μ— λ”°λ₯Έ 유효 λ²”μœ„λ₯Ό μ˜λ―Έν•˜λ©° μ’€ 더 κ΅¬μ²΄μ μœΌλ‘œλŠ” λ³€μˆ˜μ™€ κ·Έ 값이 μ–΄λ””μ„œλΆ€ν„° μ–΄λ””κΉŒμ§€ μœ νš¨ν•œκ°€μ— λŒ€ν•œ λ²”μœ„ 이닀.

μŠ€μ½”ν”„μ˜ νŠΉμ„±μ€

  • μ•ˆμͺ½ Scope μ—μ„œ λ°”κΉ₯ λ³€μˆ˜/ν•¨μˆ˜λ₯Ό μ ‘κ·Όν•˜λŠ” 것은 κ°€λŠ₯ν•˜λ‹€.
  • λ°”κΉ₯μͺ½ Scope μ—μ„œ μ•ˆμͺ½ λ³€μˆ˜/ν•¨μˆ˜λ₯Ό μ ‘κ·Όν•˜λŠ” 것은 λΆˆκ°€λŠ₯ ν•˜λ‹€.
  • Global Scope λŠ” μ΅œμƒλ‹¨μ˜ Scope 둜 μ „μ—­ λ³€μˆ˜λŠ” μ–΄λ””μ„œλ“  접근이 κ°€λŠ₯ν•˜λ‹€.
  • 지역 λ³€μˆ˜λŠ” ν•¨μˆ˜ λ‚΄μ—μ„œ μ „μ—­ λ³€μˆ˜λ³΄λ‹€ 더 높은 μš°μ„  μˆœμœ„λ₯Ό κ°€μ Έμ„œ λ¨Όμ € ν•΄λ‹Ή μ§€μ—­μ˜ λ³€μˆ˜λ₯Ό λ¨Όμ € μ°Ύκ³  μ—†λ‹€λ©΄ κ·Έ μœ„μ˜ 지역 ν˜Ήμ€ κΈ€λ‘œλ²Œ λ³€μˆ˜λ₯Ό μ°Έμ‘°ν•˜λŠ” μˆœμ„œλ‘œ 이어진닀.

let κ³Ό var 의 차이λ₯Ό 이야기 ν•˜κΈ° 전에 λ°”λ‘œ 이 Scope μ—μ„œ Function Scope 와 Block Scope 에 λŒ€ν•œ 차이λ₯Ό μ•Œμ•„μ•Ό ν•œλ‹€.

μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” 기본적으둜 ν•¨μˆ˜ λ‹¨μœ„λ‘œ μžμ‹ λ§Œμ˜ μŠ€μ½”ν”„λ₯Ό κ°€μ§€λŠ”λ° 이λ₯Ό Function Scope 라 ν•˜λ©° var λ³€μˆ˜λŠ” Function Scope λ₯Ό λ”°λ₯΄κ²Œ λœλ‹€.

ν•˜μ§€λ§Œ Curly-Bracket 으둜 이루어진 Block λ‹¨μœ„λ‘œ Scope λ₯Ό κ΅¬λΆ„ν–ˆμ„ λ•Œ Function Scope 보닀 더 μ˜ˆμΈ‘ν•˜κΈ° μ‰¬μš΄ μ½”λ“œλ₯Ό μž‘μ„±ν•  수 μžˆλ‹€.

let κ³Ό const ν‚€μ›Œλ“œκ°€ Block Scope 에 μ‚¬μš©λ˜λŠ” λ³€μˆ˜μ΄λ‹€. Block Scope μ—μ„œμ˜ λ³€μˆ˜ μ‚¬μš©μ€ ν•΄λ‹Ή 블둝 (Curly Bracket) μ•ˆμ— λ³€μˆ˜κ°€ κ°™νžˆκ²Œ λœλ‹€.

Block Scope λ₯Ό 톡해 λ³€μˆ˜μ˜ 유효 λ²”μœ„κ°€ λˆˆμ— ν™• λ“€μ–΄μ˜€λ„λ‘ ν•  수 있기 λ•Œλ¬Έμ΄λ‹€. var 을 μ‚¬μš©ν•˜λ©΄ μ˜ˆμƒμΉ˜ λͺ»ν•˜κ²Œ μž¬μ‚¬μš©μ„ ν•˜κ²Œ λ˜λŠ” μœ„ν—˜μ„±μ΄ μ‘΄μž¬ν•  수 μžˆλ‹€.

let κ³Ό const 의 유효 λ²”μœ„λŠ” κ·Έλž˜μ„œ Block Scope λ₯Ό λ”°λ₯΄λ©° 두 λ³€μˆ˜ λͺ¨λ‘ μž¬μ„ μ–Έμ΄ λΆˆκ°€λŠ₯ ν•˜λ‹€.

ν•˜μ§€λ§Œ let ν‚€μ›Œλ“œλŠ” 값을 μž¬μ •μ˜ (μž¬ν• λ‹Ή) ν•  수 μžˆμ§€λ§Œ const λŠ” 값을 μž¬μ •μ˜ ν•˜λŠ” 것이 λΆˆκ°€λŠ₯ ν•˜λ‹€.

var ν‚€μ›Œλ“œλŠ” Function Scope λ₯Ό λ”°λ₯΄λ©° (old way) κ°’ μž¬μ •μ˜μ™€ μž¬μ„ μ–Έμ΄ κ°€λŠ₯ν•˜λ‹€.

πŸ—Hoisting

var ν‚€μ›Œλ“œλŠ” μž¬μ„ μ–Έμ΄ κ°€λŠ₯ν•˜μ§€λ§Œ let 은 μž¬μ„ μ–Έμ΄ λΆˆκ°€λŠ₯ ν•˜λ‹€λŠ” 점을 염두에 λ‘” μƒνƒœμ—μ„œ λ“€μ–΄κ°€λ³΄μž.

1. var λŠ” μ„ μ–Έν•˜κΈ° 전에 μ‚¬μš©ν•  수 μžˆλ‹€.

μ•„λž˜μ˜ μ½”λ“œλ₯Ό ν•œλ²ˆμ— 개발자 도ꡬ console 에 μž…λ ₯ν›„ μ—”ν„°λ₯Ό 쳐 λ³΄μ•˜λ‹€.

console.log(myname)
var myname = 'mook'

undefined 라 λœ¨λŠ” 것 μ΄μ™Έμ—λŠ” 아무 μ—λŸ¬ λ©”μ‹œμ§€κ°€ λœ¨μ§€ μ•ŠλŠ”λ‹€.

μ™œλƒν•˜λ©΄ var 둜 μ„ μ–Έλœ λͺ¨λ“  λ³€μˆ˜λŠ” μ½”λ“œκ°€ μ‹€μ œλ‘œ μ΄λ™ν•˜μ§€λŠ” μ•Šμ§€λ§Œ μ½”λ“œκ°€ μ΅œμƒμœ„λ‘œ λŒμ–΄μ˜¬λ €μ§„ κ²ƒμ²˜λŸΌ λ™μž‘ν•˜κ²Œ λœλ‹€.

이λ₯Ό β€œHoisting” 이라 ν•œλ‹€.

var myname
console.log(myname) // undefined
myname = 'mook'

μœ„μ˜ μ½”λ“œμ²˜λŸΌ λ™μž‘ν•˜λŠ” 것이닀! 그런데 console.log μ—μ„œλŠ” undefined κ°€ λœ¨λŠ” μ΄μœ λŠ”?

그것은 λ°”λ‘œ μ„ μ–Έ (declaration) 은 ν˜Έμ΄μŠ€νŒ…μ΄ λ˜μ§€λ§Œ ν• λ‹Ή (assignment) 은 ν˜Έμ΄μŠ€νŒ…μ΄ λ˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ΄λ‹€. myname μ΄λΌλŠ” λ³€μˆ˜λ§Œ μ˜¬λ €μ§„ 것이고 β€˜mook’ μ΄λΌλŠ” ν• λ‹Ήλœ 값은 κ·Έ μžλ¦¬μ— μžˆλŠ” 것이닀.

μœ„μ˜ μ½”λ“œμ²˜λŸΌ 할당은 μ„Έ 번째 μ€„μ—μ„œ μ²˜λ¦¬κ°€ λœλ‹€.

2. let 도 ν˜Έμ΄μŠ€νŒ…μ΄ λ˜λ‚˜μš”? λœλ‹€. 그런데..

μœ„μ˜ μ½”λ“œμ™€ 같은 μƒν™©μ—μ„œ μ•„λž˜μ˜ μ½”λ“œλ₯Ό λ™μ‹œμ— 볡사해 개발자 도ꡬ에 λ„£κ³  μ—”ν„°λ₯Ό 치면,

console.log(myname)
let myname = 'mook'

referror

Reference Error λ₯Ό μΌμœΌν‚¨λ‹€.

그럼 let 을 썼을 λ•ŒλŠ” Hoisting 이 μ•ˆ λ˜λŠ” 걸까?

ν•˜μ§€λ§Œ let κ³Ό const 도 ν˜Έμ΄μŠ€νŒ…μ΄ λœλ‹€.

3. ν˜Έμ΄μŠ€νŒ…μ˜ μ •μ˜

μŠ€μ½”ν”„ λ‚΄λΆ€ μ–΄λ””μ„œλ“  λ³€μˆ˜ 선언은 μ΅œμƒμœ„μ— μ„ μ–Έλœ κ²ƒμ²˜λŸΌ ν–‰λ™ν•œλ‹€λŠ” λœ»μ΄λ‹€.

4. let 이 Reference Error λ₯Ό λ‚΄λŠ” 이유

let 도 ν˜Έμ΄μŠ€νŒ…μ΄ λœλ‹€λ©΄ μ™œ var ν‚€μ›Œλ“œ 처럼 λ™μž‘ν•˜μ§€ μ•Šκ³  레퍼런슀 μ—λŸ¬λ₯Ό λ‚ΌκΉŒ?

그것은 λ°”λ‘œ Temporal Dead Zone (TDZ) λΌλŠ” 것 λ•Œλ¬Έμ— κ·Έλ ‡λ‹€κ³  ν•œλ‹€.

let κ³Ό const ν‚€μ›Œλ“œλŠ” λ°”λ‘œ 이 TDZ 의 영ν–₯을 λ°›λŠ”λ‹€.

즉, κ°’ 할당을 ν•˜κΈ° μ „μ—λŠ” μ‚¬μš©ν•  수 μ—†λ‹€. ν• λ‹Ή μ΄μ „μ˜ μ½”λ“œλŠ” μ‚¬μš©ν•  수 μ—†λŠ” TDZ μ˜μ—­ μ΄λΌλŠ” 것이닀.

μ΄λŸ¬ν•œ 것듀은 μ½”λ“œλ₯Ό 예츑 κ°€λŠ₯ν•˜κ²Œ ν•˜κ³  잠재적인 버그λ₯Ό 쀄일 수 μžˆλ‹€κ³  ν•œλ‹€. κ·Έλž˜μ„œ var ν‚€μ›Œλ“œ λŒ€μ‹  let κ³Ό const ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ”κ°€ 보닀.

5. ν˜Έμ΄μŠ€νŒ…μ˜ μ˜ˆμ‹œ

μ²«λ²ˆμ§ΈλŠ” μ•„λ¬΄λŸ° λ¬Έμ œκ°€ μ—†λŠ” μ½”λ“œμ΄λ‹€.

let age = 30
function showAge() {
  console.log(age)
}

showAge()

ν•¨μˆ˜ showAge λ‚΄ age λΌλŠ” λ³€μˆ˜λŠ” 지역 μŠ€μ½”ν”„ λ‚΄μ—μ„œ μ°Έμ‘° ν•  수 μžˆλŠ” 값이 μ—†μœΌλ―€λ‘œ μ „μ—­ μŠ€μ½”ν”„μ— μ„ μ–Έ 및 ν• λ‹Ήλœ age λ₯Ό μ°Έμ‘°ν•  수 μžˆλ‹€. κ·ΈλŸ¬λ―€λ‘œ ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•˜λ©΄ 숫자 30 이 찍히게 될 것이닀.

자 이제 λ‘λ²ˆμ§Έλ‘œ λ¬Έμ œκ°€ λ˜λŠ” μ½”λ“œλ₯Ό μ†Œκ°œν•œλ‹€.

let age = 30
function showAge() {
  console.log(age)
  let age = 20
}

showAge()

referror2

let 은 hoisting 이 λ˜μ§€ μ•ŠλŠ”λ‹€κ³  μƒκ°ν•˜κ²Œ λœλ‹€. ν•˜μ§€λ§Œ μ΄λŠ” 사싀이 μ•„λ‹ˆλ‹€.

hoisting 은 μŠ€μ½”ν”„ λ‹¨μœ„λ‘œ μΌμ–΄λ‚˜λŠ”λ° μœ„μ˜ μ½”λ“œ 처럼 curly bracket 의 block μŠ€μ½”ν”„ λ‚΄μ—μ„œ let μ—­μ‹œλ„ hoisting 이 μΌμ–΄λ‚˜λŠ”λ°,

λ§Œμ•½ let 이 hoisting 이 μΌμ–΄λ‚˜μ§€ μ•ŠλŠ”λ‹€λ©΄ age = 30 이 μ°ν˜”μ–΄μ•Ό ν•  것이닀.

let age = 30
function showAge() {
  let age
  console.log(age)
  age = 20
}

let μ—μ„œ block scope λ‚΄ ν˜Έμ΄μŠ€νŒ…μ΄ μΌμ–΄λ‚˜λŠ” μ½”λ“œλ₯Ό 정리해 λ³΄μ•˜λ‹€.

전역에 이미 age κ°€ let 으둜 μ„ μ–Έλ˜μ–΄ μžˆλŠ”λ° 블둝 μŠ€μ½”ν”„ λ‚΄μ—μ„œ age κ°€ let 으둜 μž¬μ„ μ–Έ λ˜μ–΄ μžˆλŠ” λͺ¨μŠ΅μ„ 확인할 수 μžˆλ‹€.

μ•žμ„œ μ„œλ‘μ— μ„€λͺ…ν–ˆλ“― let 은 μž¬μ„ μ–Έμ΄ λΆˆκ°€λŠ₯ ν•˜λ‹€κ³  ν–ˆλ‹€.

6. λ³€μˆ˜μ˜ 3단계 생성 κ³Όμ •

λ³€μˆ˜λŠ” 3λ‹¨κ³„μ˜ 생성 과정을 κ±°μΉœλ‹€.

  1. μ„ μ–Έ 단계
  2. μ΄ˆκΈ°ν™” 단계
  3. ν• λ‹Ή 단계

var ν‚€μ›Œλ“œλŠ”,

  1. μ„ μ–Έ 및 μ΄ˆκΈ°ν™” 단계가 λ™μ‹œμ— μΌμ–΄λ‚œλ‹€.
  2. ν• λ‹Ή 단계

μ—¬κΈ°μ„œ μ΄ˆκΈ°ν™”λž€ undefined λ₯Ό ν• λ‹Ήν•΄ μ£ΌλŠ” 단계λ₯Ό μ˜λ―Έν•œλ‹€. κ·Έλž˜μ„œ μ•„κΉŒ 였λ₯˜λ₯Ό μΌμœΌν‚€μ§€ μ•Šκ³  undefined λ₯Ό μ½˜μ†”μ— 좜λ ₯ν•΄ λ³΄μ—¬μ€¬λ˜ 것이닀.

let ν‚€μ›Œλ“œλŠ” 맨 μœ„μ²˜λŸΌ μ„ μ–Έ 단계와 μ΄ˆκΈ°ν™” 단계가 뢄리 λ˜μ–΄μ„œ μ§„ν–‰λœλ‹€.

μ΄ˆκΈ°ν™” λ‹¨κ³„λŠ” μ‹€μ œ μ½”λ“œμ— λ„λ‹¬ν–ˆμ„ λ•Œ μ§„ν–‰λ˜κΈ° λ•Œλ¬Έμ— Reference Error κ°€ μΌμ–΄λ‚œλ‹€.

const ν‚€μ›Œλ“œλŠ”,

μ„ μ–Έ + μ΄ˆκΈ°ν™” + ν• λ‹Ή 이 λ™μ‹œμ— 이루어진닀. (그렇지 μ•ŠμœΌλ©΄ μ—λŸ¬κ°€ λ°œμƒ) μ™œλƒν•˜λ©΄ let κ³Ό var 은 값을 λ°”κΏ€ 수 있기 (μž¬ν• λ‹Ή) λ•Œλ¬Έμ΄μ§€λ§Œ const λŠ” 그렇지 μ•ŠκΈ° λ•Œλ¬Έμ΄λ‹€.

let myname;
myname = 'mook'

var age;
age = 25

const gender
gender = 'male' // Error

const gender λΆ€λΆ„μ—μ„œ μ—λŸ¬κ°€ λ°œμƒν•œλ‹€. κ·Έ μ΄μœ λŠ” μ„ μ–Έν•˜λ©΄μ„œ λ°”λ‘œ 할당을 ν•˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ΄λ‹€.

즉 μ„ μ–Έ + μ΄ˆκΈ°ν™” + ν• λ‹Ή 이 λ™μ‹œμ— 이루어지지 μ•Šμ•˜κΈ° λ•Œλ¬Έμ΄λ‹€.

πŸ—Scope (var, let, const)

var λŠ” ν•¨μˆ˜ μŠ€μ½”ν”„μ΄λ©°, let κ³Ό const ν‚€μ›Œλ“œλŠ” 블둝 μŠ€μ½”ν”„λ₯Ό 가진닀.

(ν•¨μˆ˜, ifλ¬Έ, forλ¬Έ, whileλ¬Έ, try/catch λ¬Έ 등을 의미)

블둝 μŠ€μ½”ν”„λž€ μ„ μ–Έλœ curly bracket 의 μ½”λ“œ 블둝 λ‚΄μ—μ„œλ§Œ λ³€μˆ˜κ°€ μœ νš¨ν•˜λ©° μ™ΈλΆ€μ—μ„œ 블둝 μŠ€μ½”ν”„ λ‚΄μ˜ λ³€μˆ˜μ— μ ‘κ·Όν•  수 μ—†λ‹€λŠ” μ˜λ―Έμ΄λ‹€.

즉 μ½”λ“œ 블둝 λ‚΄λΆ€μ—μ„œ μ„ μ–Έν•œ λ³€μˆ˜λŠ” 지역 λ³€μˆ˜μ΄λ‹€.

var λŠ” ν•¨μˆ˜ μŠ€μ½”ν”„ 이닀.

const age = 30

if (age > 19) {
  var txt = '성인'
}

console.log(txt) // '성인' 이 μ°νžŒλ‹€.

이처럼 var λŠ” κ°€λŠ₯ν•˜μ§€λ§Œ let κ³Ό const λŠ” μ€‘κ΄„ν˜Έ λ‚΄λΆ€ μ•ˆμ—μ„œλ§Œ λ³€μˆ˜λ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

ν•΄λ‹Ή μ½”λ“œμ²˜λŸΌ μ™ΈλΆ€μ—μ„œ 접근이 λΆˆκ°€λŠ₯ ν•˜λ‹€λŠ” λœ»μ΄λ‹€.

var λ˜ν•œ ν•¨μˆ˜ μŠ€μ½”ν”„ μ΄λ―€λ‘œ,

function add(num1, num2) {
  var result = num1 + num2
}

add(2, 3)
console.log(result)

referror3

Reference Error λ₯Ό μΌμœΌν‚¨λ‹€. var 도 ν•¨μˆ˜ λ‚΄μ—μ„œλ§Œ λ³€μˆ˜ μ°Έμ‘°κ°€ κ°€λŠ₯ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.

var κ°€ μœ μΌν•˜κ²Œ λ²—μ–΄λ‚  수 μ—†λŠ” μŠ€μ½”ν”„κ°€ ν•¨μˆ˜λΌκ³  μƒκ°ν•˜λ©΄ λœλ‹€.

πŸ—κ²°λ‘ 

예츑 κ°€λŠ₯ν•œ κ²°κ³Όλ₯Ό λ‚΄κ³  버그λ₯Ό 쀄이기 μœ„ν•΄ let κ³Ό const μ‚¬μš©μ„ ꢌμž₯ν•œλ‹€.

μΆ”κ°€λ‘œ 읽은 λΈ”λ‘œκ·Έ (μΊ‘ν‹΄νŒκ΅λ‹˜ λΈ”λ‘œκ·Έ - ν•¨μˆ˜μ„ μ–Έμ‹, ν‘œν˜„μ‹μ˜ ν˜Έμ΄μŠ€νŒ…)

https://joshua1988.github.io/web-development/javascript/function-expressions-vs-declarations/


Written by@[DotoriMook]
ν”„λ‘ νŠΈμ—”λ“œ μ£Όλ‹ˆμ–΄ 개발자 λ„ν† λ¦¬λ¬΅μ˜ 기술개발 λΈ”λ‘œκ·Έ μž…λ‹ˆλ‹€.

GitHubMediumTwitterFacebook