πŸ“‹ λͺ¨λ˜ μžλ°”μŠ€ν¬λ¦½νŠΈ Deep Dive | 15μž₯ let, const ν‚€μ›Œλ“œμ™€ 블둝 레벨 μŠ€μ½”ν”„

waterglassesΒ·2022λ…„ 4μ›” 10일
0
post-thumbnail

λͺ¨λ˜ μžλ°”μŠ€ν¬λ¦½νŠΈ Deep Dive λ„μ„œμ˜ 15μž₯을 μ •λ¦¬ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

15.1 var ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ λ³€μˆ˜μ˜ 문제점

15.1.1 λ³€μˆ˜ 쀑볡 μ„ μ–Έ ν—ˆμš©

var ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ λ³€μˆ˜λŠ” 쀑볡 선언이 κ°€λŠ₯ν•˜λ‹€.

var x = 1;
var x = 100;
console.log(x); // 100

λ™μΌν•œ μ΄λ¦„μ˜ λ³€μˆ˜κ°€ 이미 μ„ μ–Έλ˜μ–΄ μžˆλŠ” 것을 λͺ¨λ₯΄κ³  λ³€μˆ˜λ₯Ό 쀑볡 μ„œμ–Έ ν•˜λ©΄μ„œ κ°’κΉŒμ§€ ν• λ‹Ήν–ˆλ‹€λ©΄ λ¨Όμ € μ„ μ–Έλœ λ³€μˆ˜ 값이 λ³€κ²½λ˜λŠ” λΆ€μž‘μš©μ΄ λ°œμƒν•œλ‹€.

15.1.2 ν•¨μˆ˜ 레벨 μŠ€μ½”ν”„

var ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ λ³€μˆ˜λŠ” 였직 ν•¨μˆ˜μ˜ μ½”λ“œ λΆˆλ‘λ§Œμ„ 지역 μŠ€μ½”ν”„λ‘œ μΈμ •ν•œλ‹€. λ”°λΌμ„œ ν•¨μˆ˜ μ™ΈλΆ€μ—μ„œ μ„ μ–Έν•œ λ³€μˆ˜λŠ” μ½”λ“œ 블둝 λ‚΄μ—μ„œ 선언해도 λͺ¨λ‘ μ „μ—­ λ³€μˆ˜κ°€ λœλ‹€.

var i = 10;
for(var i = 0; i<5; i++){
	console.log(i);// 0 1 2 3 4
}
console.log(i); //5

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

λ³€μˆ˜ ν˜Έμ΄μŠ€νŒ…μ— μ˜ν•΄ var ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ λ³€μˆ˜λŠ” λ³€μˆ˜ μ„ μ–Έλ¬Έ 이전에 μ°Έμ‘°ν•  수 μžˆλ‹€. 단 ν• λ‹Ήλ¬Έ 이전에 λ³€μˆ˜λ₯Ό μ°Έμ‘°ν•˜λ©΄ undefinedλ₯Ό λ°˜ν™˜ν•œλ‹€.

console.log(x); // undefined
x = 123;
console.log(x); //123
var x;

λ³€μˆ˜ μ„ μ–Έλ¬Έ 이전에 λ³€μˆ˜λ₯Ό μ°Έμ‘°ν•˜λŠ” 것은 ν”„λ‘œκ·Έλž¨ 흐름상 λ§žμ§€ μ•Šμ„ λΏλ”λŸ¬ 가독성을 λ–¨μ–΄λœ¨λ¦¬κ³  였λ₯˜λ₯Ό λ°œμƒμ‹œν‚¬ 여지λ₯Ό 남긴닀.

15.2 let ν‚€μ›Œλ“œ

15.2.1 λ³€μˆ˜ 쀑볡 μ„ μ–Έ κΈˆμ§€

let ν‚€μ›Œλ“œλ‘œ 이름이 같은 λ³€μˆ˜λ₯Ό 쀑볡 μ„ μ–Έν•˜λ©΄ SyntaxError(λ¬Έλ²•μ—λŸ¬)κ°€ λ°œμƒν•œλ‹€.

let a = 123;
let a = 456; // SyntaxError 

15.2.2 블둝 레벨 μŠ€μ½”ν”„

let ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ λ³€μˆ˜λŠ” λͺ¨λ“  μ½”λ“œ 블둝(ν•¨μˆ˜, ifλ¬Έ, for, whileλ¬Έ λ“±)을 지역 μŠ€μ½”ν”„λ‘œ μΈμ •ν•˜λŠ” 블둝 레벨 μŠ€μ½”ν”„λ₯Ό λ”°λ₯Έλ‹€.

let i = 100;
function foo(){
	let i = 100;
    for(let i = 0; i<3; i++){
    	console.log(i); //1 2
    }
    console.log(i); //100
}
foo();
console.log(i); //10

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

let ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ λ³€μˆ˜λŠ” λ³€μˆ˜ ν˜Έμ΄μŠ€νŒ…μ΄ λ°œμƒ ν•˜μ§€ μ•ŠλŠ” κ²ƒμ²˜λŸΌ λ™μž‘ν•œλ‹€.

console.log(x); //ReferenceError: x is not defined
let x;

var ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ λ³€μˆ˜

  • λŸ°νƒ€μž„ 이전에 μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진에 μ˜ν•΄ μ•”λ¬΅μ μœΌλ‘œ "μ„ μ–Έ 단계"와 "μ΄ˆκΈ°ν™” 단계"κ°€ ν•œλ²ˆμ— μ§„ν–‰λœλ‹€.

let ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ λ³€μˆ˜

  • "μ„ μ–Έ 단계"와 "μ΄ˆκΈ°ν™” 단계"κ°€ λΆ„λ¦¬λ˜μ–΄ μ§„ν–‰λœλ‹€.
  • λŸ°νƒ€μž„ 이전에 μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진에 μ˜ν•΄ μ•”λ¬΅μ μœΌλ‘œ "μ„ μ–Έ 단계"κ°€ λ¨Όμ € μ‹€ν–‰λ˜μ§€λ§Œ μ΄ˆκΈ°ν™” λ‹¨κ³„λŠ” λ³€μˆ˜ 선언문이 λ„λ‹¬ν–ˆμ„ λ•Œ μ‹€ν–‰λœλ‹€.

λ§Œμ•½, μ΄ˆκΈ°ν™” 단계가 μ‹€ν–‰λ˜κΈ° 이전에 λ³€μˆ˜μ— μ ‘κ·Όν•˜λ €κ³  ν•˜λ©΄ μ°Έμ‘° μ—λŸ¬κ°€ λ°œμƒν•œλ‹€.
let ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ λ³€μˆ˜λŠ” μŠ€μ½”ν”„μ˜ μ‹œμž‘μ§€μ λΆ€ν„° λ³€μˆ˜ μ„ μ–Έλ¬ΈκΉŒμ§€ λ³€μˆ˜λ₯Ό μ°Έμ‘°ν•  수 μ—†λ‹€. 이 ꡬ간을 μΌμ‹œμ  μ‚¬κ°μ§€λŒ€(TDZ)라고 λΆ€λ₯Έλ‹€.

// λŸ°νƒ€μž„ 이전에 μ„ μ–Έ 단계 μ‹€ν–‰(λ³€μˆ˜ μ΄ˆκΈ°ν™” X)
// μ΄ˆκΈ°ν™” μ΄μ „μ˜ μΌμ‹œμ  μ‚¬κ°μ§€λŒ€(TDZ)μ—μ„œλŠ” λ³€μˆ˜λ₯Ό μ°Έμ£Όν•  수 μ—†λ‹€.
console.log(foo); //ReferenceError

let foo; //μ΄ˆκΈ°ν™” 단계
console.log(foo); //undefined

foo = 1; //ν• λ‹Ή 단계

πŸ–πŸ» μ—¬κΈ°μ„œ 잠깐!
let ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ λ³€μˆ˜λŠ” λ³€μˆ˜ ν˜Έμ΄μŠ€νŒ…μ΄ λ°œμƒν•˜μ§€ μ•ŠλŠ” κ²ƒμ²˜λŸΌ λ³΄μ΄μ§€λ§Œ μ•„λ‹ˆλ‹€!

lef foo = 1;
{
	console.log(foo); //ReferenceError
    let foo = 2;
}

μœ„μ˜ μ½˜μ†”μ—μ„œ foo의 값이 1이 λ‚˜μ˜¬ 것 처럼 λ³΄μ΄μ§€λ§Œ 블둝 μ•ˆμ—μ„œ ν˜Έμ΄μŠ€νŒ…μ΄ λ°œμƒν•˜κΈ° λ•Œλ¬Έμ— ReferenceErrorκ°€ λ°œμƒν•œλ‹€.
-> ES6μ—μ„œ λ„μž…λœ λͺ¨λ“  선언은 ν˜Έμ΄μŠ€νŒ…ν•œλ‹€.

15.2.4 μ „μ—­ 객체와 let

varν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ μ „μ—­ λ³€μˆ˜μ™€ μ „μ—­ ν•¨μˆ˜, 그리고 μ„ μ–Έν•˜μ§€ μ•Šμ€ λ³€μˆ˜μ— 값을 ν• λ‹Ήν•œ 암묡적 전역은 μ „μ—­ 객체 window의 ν”„λ‘œνΌν‹°κ°€ λœλ‹€.

// 이 μ˜ˆμ œλŠ” λΈŒλΌμš°μ € ν™˜κ²½μ—μ„œ μ‹€ν–‰ν•΄μ•Ό ν•œλ‹€.
var x = 1;
y = 2;
function foo(){}

console.log(window.x); //1 : var ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•΄μ„œ window의 ν”„λ‘œνΌν‹°κ°€ 됨.
console.log(x); //μ „μ—­ 객체 window의 ν”„λ‘œνΌν‹°λŠ” μ „μ—­ λ³€μˆ˜μ²˜λŸΌ μ‚¬μš©ν•  수 μžˆλ‹€.

// 암묡적 μ „μ—­
console.log(window.y); //2
console.log(y); //2

// ν•¨μˆ˜ μ„ μ–Έλ¬ΈμœΌλ‘œ μ •μ˜ν•œ μ „μ—­ ν•¨μˆ˜λŠ” μ „μ—­ 객체 window의 ν”„λ‘œνΌν‹°λ‹€.
console.log(window.foo);
console.log(foo); //f foo(){}

❓ 암묡적 μ „μ—­μ΄λž€?

μ„ μ–Έν•˜μ§€ μ•Šμ€ μ‹λ³„μžμ— 값을 ν• λ‹Ήν•˜λ©΄ μ „μ—­κ°μ²΄μ˜ ν”„λ‘œνΌν‹°κ°€ λœλ‹€. μ΄λŠ” λ³€μˆ˜κ°€ μ•„λ‹ˆλ‹€.
밑에 μ˜ˆμ‹œμ²˜λŸΌ window.y = 2처럼 ν•΄μ„λ˜μ–΄, μ „μ—­κ°μ²΄μ˜ ν”„λ‘œνΌν‹°κ°€ λ˜λŠ” 것이닀. μ΄λŸ¬ν•œ ν˜„μƒμ„ 암묡적 전역이라고 λ§ν•œλ‹€.

var x = 10;
function foo(){
  y = 20; //window.y
  console.log(x+y); //30
}
foo(); // 30

λ°‘μ˜ μ˜ˆμ‹œμ²˜λŸΌ yλŠ” λ³€μˆ˜κ°€ μ•„λ‹ˆλ―€λ‘œ ν˜Έμ΄μŠ€νŒ…μ΄ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€!

// μ „μ—­ λ³€μˆ˜ xλŠ” ν˜Έμ΄μŠ€νŒ…μ΄ λ°œμƒν•œλ‹€.
console.log(x); // undefined
// μ „μ—­ λ³€μˆ˜κ°€ μ•„λ‹ˆλΌ 단지 μ „μ—­ ν”„λ‘œνΌν‹°μΈ yλŠ” ν˜Έμ΄μŠ€νŒ…μ΄ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€.
console.log(y); // ReferenceError: y is not defined

var x = 10; // μ „μ—­ λ³€μˆ˜

function foo () {
  // μ„ μ–Έν•˜μ§€ μ•Šμ€ λ³€μˆ˜
  y = 20;
  console.log(x + y); //30
}
foo(); // 30

const ν‚€μ›Œλ“œ

λŒ€λΆ€λΆ„ let ν‚€μ›Œλ“œμ™€ λ™μΌν•œ νŠΉμ§•μ„ 가진닀.

15.3.1 μ„ μ–Έκ³Ό μ΄ˆκΈ°ν™”

const ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ λ³€μˆ˜λŠ” λ°˜λ“œμ‹œ μ„ μ–Έκ³Ό λ™μ‹œμ— μ΄ˆκΈ°ν™”ν•΄μ•Ό ν•œλ‹€.
그렇지 μ•ŠμœΌλ©΄ SyntaxError(문법 μ—λŸ¬)κ°€ λ°œμƒν•œλ‹€. 그리고 let ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ λ³€μˆ˜μ™€ λ§ˆμ°¬κ°€μ§€λ‘œ 블둝 레벨 μŠ€μ½”ν”„λ₯Ό 가지며, λ³€μˆ˜ ν˜Έμ΄μŠ€νŒ…μ΄ λ°œμƒν•˜μ§€ μ•ŠλŠ” κ²ƒμ²˜λŸΌ λ™μž‘ν•œλ‹€.

15.3.2 μž¬ν• λ‹Ή κΈˆμ§€

var λ˜λŠ” let ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ λ³€μˆ˜λŠ” μž¬ν• λ‹Ήμ΄ μžμœ λ‘œμš°λ‚˜ const ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ λ³€μˆ˜λŠ” μž¬ν• λ‹Ήμ΄ κΈˆμ§€λœλ‹€.

const foo = 1;
foo = 2; //TypeError: Assignment to constant variable.

15.3.3 μƒμˆ˜

λ³€μˆ˜μ˜ μƒλŒ€ κ°œλ…μœΌλ‘œ μž¬ν• λ‹Ήμ΄ κΈˆμ§€λœ λ³€μˆ˜λ₯Ό λ§ν•œλ‹€. μƒμˆ˜λ„ 값을 μ €μž₯ν•˜κΈ° μœ„ν•œ λ©”λͺ¨λ¦¬ 곡간이 ν•„μš”ν•˜λ―€λ‘œ λ³€μˆ˜λΌκ³  ν•  수 μžˆλ‹€. 단, λ³€μˆ˜λŠ” μ–Έμ œλ“ μ§€ μž¬ν• λ‹Ήμ„ 톡해 λ³€μˆ˜ 값을 λ³€κ²½ν•  수 μžˆμ§€λ§Œ μƒμˆ˜λŠ” μž¬ν• λ‹Ήμ΄ κΈˆμ§€λœλ‹€. μƒμˆ˜λŠ” μƒνƒœ μœ μ§€μ™€ 가독성, μœ μ§€λ³΄μˆ˜μ˜ νŽΈμ˜μ„ μœ„ν•΄ 적극적으둜 μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.

즉, const ν‚€μ›Œλ“œλ‘œ μ„ μ–Έλœ λ³€μˆ˜μ— μ›μ‹œ 값을 ν• λ‹Ήν•  경우 μ›μ‹œκ°’μ€ λ³€κ²½ν•  수 μ—†λŠ” 값이고 const ν‚€μ›Œλ“œλŠ” μž¬ν• λ‹Ήμ΄ κΈˆμ§€λ˜λ―€λ‘œ ν• λ‹Ήλœ 값을 λ³€κ²½ν•  방법이 μ—†λ‹€.

μ•„λž˜ μ˜ˆμ‹œμ²˜λŸΌ 0.1을 μ–΄λ–€ 의미둜 μ‚¬μš©ν–ˆλŠ”μ§€ λͺ…ν™•ν•˜κ²Œ μ•ŒκΈ° μœ„ν•΄μ„œ μƒμˆ˜λ‘œ μ •μ˜ν•΄μ„œ μ‚¬μš©ν•˜λŠ” 방법도 μžˆλ‹€.
μ—¬λŸ¬ λ‹¨μ–΄λ‘œ 이루어진 κ²½μš°λŠ” μŠ€λ„€μ΄ν¬ μΌ€μ΄μŠ€('_'둜 ꡬ뢄)둜 ν‘œν˜„ν•˜λŠ” 것이 μΌλ°˜μ μ΄λ‹€.

const TAX_RATE = 0.1; // μ„Έμœ¨
let preTaxPrice = 100; // μ„Έμ „ 가격
let afterTaxPrice = preTaxPrice + (preTaxPrice * TAX_RATE) // μ„Έν›„ 가격

console.log(afterTaxPrice); //110

15.3.4 const ν‚€μ›Œλ“œμ™€ 객체

const ν‚€μ›Œλ“œλ‘œ μ„ μ–Έλœ λ³€μˆ˜μ— 객체λ₯Ό ν• λ‹Ήν•œ κ²½μš°μ—λŠ” 값을 λ³€κ²½ν•  수 μžˆλ‹€.

const person = {
	name: 'Lee'
}

// κ°μ²΄λŠ” λ³€κ²½ κ°€λŠ₯ν•œ 값이닀. λ”°λΌμ„œ μž¬ν• λ‹Ή 없이 변경이 κ°€λŠ₯ν•˜λ‹€.
person.name = 'Kim';
console.log(person); //{name:'Kim'}

-> const ν‚€μ›Œλ“œλŠ” μž¬ν• λ‹Ήμ„ κΈˆμ§€ν•  뿐 λΆˆλ³€μ„ μ˜λ―Έν•˜λŠ” 것은 μ•„λ‹ˆλ‹€. 즉, μƒˆλ‘œμš΄ 값을 μž¬ν• λ‹Ήν•˜λŠ” 것은 κΈˆμ§€ν•˜μ§€λ§Œ ν”„λ‘œνΌν‹° 동적 생성, μ‚­μ œ, ν”„λ‘œνΌν‹° κ°’μ˜ 변경을 톡해 객체λ₯Ό λ³€κ²½ν•˜λŠ” 것은 κ°€λŠ₯ν•œλ‹€.

15.4 var VS let VS const

λ³€μˆ˜ μ„ μ–Έμ—λŠ” 기본적으둜 constλ₯Ό μ‚¬μš©ν•˜κ³  let은 μž¬ν• λ‹Ήμ΄ ν•„μš”ν•œ κ²½μš°μ— ν•œμ •ν•΄ μ‚¬μš©ν•˜λŠ” 것이 μ’‹λ‹€.

  1. ES6λ₯Ό μ‚¬μš©ν•œλ‹€λ©΄ var ν‚€μ›Œλ“œλŠ” μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€.
  2. μž¬ν• λ‹Ήμ΄ ν•„μš”ν•œ κ²½μš°μ—λ§Œ ν•œμ •ν•˜μ—¬ let ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•œλ‹€. μ΄λ•Œ λ³€μˆ˜μ˜ μŠ€μ½”ν”„λŠ” μ΅œλŒ€ν•œ 쒁게 λ§Œλ“ λ‹€.
  3. 변경이 λ°œμƒν•˜μ§€ μ•Šκ³  읽기 μ „μš©μœΌλ‘œ μ‚¬μš©ν•˜λŠ”(μž¬ν• λ‹Ήμ΄ ν•„μš” μ—†λŠ” μƒμˆ˜) μ›μ‹œκ°’κ³Ό κ°μ²΄μ—λŠ” constλ₯Ό μ‚¬μš©ν•œλ‹€.

λ³€μˆ˜λ₯Ό μ„ μ–Έν•˜λŠ” μ‹œμ μ—λŠ” μž¬ν• λ‹Ήμ΄ ν•„μš”ν•œμ§€ 잘 λͺ¨λ₯΄λŠ” κ²½μš°κ°€ λ§Žλ‹€. λ”°λΌμ„œ 일단 const ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜κ³  μž¬ν• λ‹Ήμ΄ ν•„μš”ν•œλ‹€λ©΄(λ°˜λ“œμ‹œ ν•„μš”ν•œμ§€ κΌ­ 생각) κ·Έλ•Œ const ν‚€μ›Œλ“œλ₯Ό let ν‚€μ›Œλ“œλ‘œ λ³€κ²½ν•˜μž.

Ref

  • 이웅λͺ¨ μ €, ⌜λͺ¨λ˜ μžλ°”μŠ€ν¬λ¦½νŠΈ Deep Dive⌟, μœ„ν‚€λΆμŠ€
  • 암묡적 μ „μ—­
profile
맀 μˆœκ°„ μ„±μž₯ν•˜λŠ” κ°œλ°œμžκ°€ 되렀고 λ…Έλ ₯ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

0개의 λŒ“κΈ€