πŸͺ© μŠ€μ½”ν”„(Scope)에 λŒ€ν•˜μ—¬

앙두·2023λ…„ 4μ›” 8일
0

for My Programming

λͺ©λ‘ 보기
9/20

λͺ¨λ“  μ˜ˆμ‹œλŠ”, μ„ μ–Έ ν‚€μ›Œλ“œ var 을 μ‚¬μš©ν•˜κ³  μžˆλ‹€λŠ” 점을 κ°μ•ˆν•΄μ£Όμ„Έμš”
쀑간쀑간, ES6 의 μ„ μ–Έ ν‚€μ›Œλ“œ let, const κ΄€λ ¨ 보좩 μ„€λͺ…이 μžˆμœΌλ‹ˆ, μ°Έκ³ ν•˜λ©° μ½μ–΄μ£Όμ„Έμš”! ✨




πŸͺ© μŠ€μ½”ν”„(Scope) ?

scope; μ˜μ—­, λ²”μœ„, μœ νš¨ν•˜λ‹€

"μœ νš¨ν•˜λ‹€" = "μ°Έμ‘°(μ ‘κ·Ό)ν•  수 μžˆλ‹€"

μŠ€μ½”ν”„λž€, μ‹λ³„μžμ˜ 유효 λ²”μœ„

  • ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ—μ„œμ˜ μœ νš¨λ²”μœ„λž€, μ–΄λŠ λ²”μœ„κΉŒμ§€ μ°Έμ‘° ν•˜λŠλƒ 이닀. λ³€μˆ˜μ™€ λ§€κ°œλ³€μˆ˜μ˜ 접근성이 μ–΄λ””κΉŒμ§€ μœ νš¨ν•œκ°€ 이닀.
  • μ‹λ³„μžλž€ λ³€μˆ˜λͺ…, ν•¨μˆ˜λͺ… 같이 λ‹€λ₯Έ λŒ€μƒκ³Ό κ΅¬λΆ„ν•˜μ—¬ 식별할 수 μžˆλŠ” μœ μΌν•œ 이름이닀. ( κ·Έλƒ₯ λ³€μˆ˜λͺ…, ν•¨μˆ˜λͺ…, 클래슀λͺ… 등을 λœ»ν•œλ‹€. μ„€λͺ…은 괜히 μ–΄λ ΅λ‹€. )
  • μŠ€μ½”ν”„λŠ” JSμ—λ§Œ κ΅­ν•œλœ κ°œλ…μ΄ μ•„λ‹Œ, λͺ¨λ“  ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ˜ 기본적인 κ°œλ…μœΌλ‘œ, ν™•μ‹€ν•œ 이해가 ν•„μš”ν•˜λ‹€.

πŸͺ© μŠ€μ½”ν”„(Scope)의 ꡬ뢄

크게 μ „μ—­ μŠ€μ½”ν”„(Global Scope) 와 지역 μŠ€μ½”ν”„(Local Scope) 둜 λ‚˜λ‰©λ‹ˆλ‹€.

μ „μ—­ μŠ€μ½”ν”„(Global Scope)

μ „μ—­ (ν•¨μˆ˜, 블둝{...} λ°–μ˜ μ˜μ—­) 에 λ³€μˆ˜λ₯Ό μ„ μ–Έν•˜λ©΄, 이 λ³€μˆ˜λŠ” μ–΄λ””μ„œλ“ μ§€ μ°Έμ‘°ν•  수 μžˆλŠ” μ „μ—­ μŠ€μ½”ν”„λ₯Ό κ°–λŠ” μ „μ—­ λ³€μˆ˜κ°€ λ©λ‹ˆλ‹€.
( λΈŒλΌμš°μ €μ—μ„œ 전역은, window 객체λ₯Ό λœ»ν•©λ‹ˆλ‹€. window λŠ” μ „μ—­ κ°μ²΄μž…λ‹ˆλ‹€. )

var global = 'global';

function hello() {
	var local = 'local';
    console.log(global);
  	console.log(local);
};

hello(); // 'global', 'local'
console.log(local); // ReferenceError: local is not defined
console.log(global); // 'global'

ν•¨μˆ˜ hello μ•ˆμ—μ„œλ„, λ°–μ—μ„œλ„ λ³€μˆ˜ global에 μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€.
μ „μ—­ μ–΄λ””μ„œλ“ μ§€ 접근이 κ°€λŠ₯ν•˜κ³ , μ „μ—­μ—μ„œ μœ νš¨ν•©λ‹ˆλ‹€.

β—οΈκ·ΈλŸ¬λ‚˜ 주의 🚨

μ „μ—­ λ³€μˆ˜λŠ” μ‚¬μš©μ„ 지양해야 ν•©λ‹ˆλ‹€.
λ³€μˆ˜ 이름이 쀑볡될 κ°€λŠ₯성이 높아지고,
그둜 μΈν•œ μ˜λ„μΉ˜ μ•Šμ€ μž¬ν• λ‹Ήμ΄ μƒνƒœ λ³€ν™”λ₯Ό μΌμœΌν‚€λ―€λ‘œ,
μ½”λ“œμ˜ 였λ₯˜λ₯Ό μ˜ˆμΈ‘ν•˜κΈ°κ°€ μ–΄λ €μ›Œμ§€κΈ° λ•Œλ¬Έμ— μ‚¬μš©μ„ μ§€μ–‘ν•΄μ•Όν•©λ‹ˆλ‹€.

지역 μŠ€μ½”ν”„(Local Scope)

λΉ„ 블둝 레벨 μŠ€μ½”ν”„(Non block-level Scope)

μ›λž˜ JSλŠ” 블둝 레벨 μŠ€μ½”ν”„λ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

if(true) {
	var x = 1;
};

console.log(x) // 1

λ³€μˆ˜ x κ°€ ν•¨μˆ˜κ°€ μ•„λ‹Œ ifλ¬Έ 블둝 λ‚΄μ—μ„œ μ„ μ–Έλ˜μ—ˆμŠ΅λ‹ˆλ‹€.
ν•¨μˆ˜ λ°–μ—μ„œ μ„ μ–Έλœ λ³€μˆ˜λŠ” μ½”λ“œ 블둝({...})λ‚΄μ—μ„œ μ„ μ–Έλ˜μ—ˆλ‹€ν• μ§€λΌλ„ λͺ¨λ‘ μ „μ—­ μŠ€μ½”ν”„λ₯Ό κ°–κ²Œ λ©λ‹ˆλ‹€.

✨ κ·ΈλŸ¬λ‚˜ ES6λΆ€ν„° νƒ„μƒν•œ let, const ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•  경우,
μ½”λ“œ 블둝({...})λ‚΄μ—μ„œ λ³€μˆ˜κ°€ μ„ μ–Έλ˜λ©΄, μ½”λ“œ 블둝 λ‚΄μ—μ„œλ§Œ λ³€μˆ˜κ°€ μž‘λ™ν•˜κ²Œ λ©λ‹ˆλ‹€.

if(true) {
	let x = 1;
};

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

ν•¨μˆ˜ 레벨 μŠ€μ½”ν”„(Function-level Scope)

JSλŠ” ν•¨μˆ˜ 레벨 μŠ€μ½”ν”„λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.
(let, const λ₯Ό μ‚¬μš©ν•˜λ©΄ 블둝 레벨 μŠ€μ½”ν”„λ‘œ μ‚¬μš©λ©λ‹ˆλ‹€.)
ν•¨μˆ˜ λ‚΄μ—μ„œ μ„ μ–Έλœ λ§€κ°œλ³€μˆ˜μ™€ λ³€μˆ˜λŠ” ν•¨μˆ˜ μ™ΈλΆ€μ—μ„œ μœ νš¨ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

var a = 5;

function apple() {
	var a = 10;
  	var b = 20;
}

console.log(a) // 5
console.log(b) // ReferenceError: b is not defined

λ³€μˆ˜ b λŠ” ν•¨μˆ˜ apple λ‚΄μ—μ„œ μ„ μ–Έλœ 지역 λ³€μˆ˜μ΄κΈ° λ•Œλ¬Έμ—, ν•¨μˆ˜ μ™ΈλΆ€μ—μ„œ μ ‘κ·Όν•  수 μ—†μŠ΅λ‹ˆλ‹€. ( ReferenceError λ°œμƒ )

κ·ΈλŸ¬λ‚˜ ν•¨μˆ˜(지역, local)μ˜μ—­μ—μ„œλŠ” μ „μ—­λ³€μˆ˜λ₯Ό μ°Έμ‘°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
μœ„μ—μ„œ μ„€λͺ…λ“œλ Έλ“―, μ „μ—­ μŠ€μ½”ν”„, μ „μ—­ λ³€μˆ˜λŠ” μ–΄λ””μ„œλ“ μ§€ μ ‘κ·Όκ°€λŠ₯ 및 μ°Έμ‘°ν•  수 있기 λ•Œλ¬Έμž…λ‹ˆλ‹€.

var x = 100;

function apple() {
	x = 300;
  	console.log(x);
};

apple(); // 300
console.log(x); // 300

λ‚΄λΆ€ ν•¨μˆ˜λŠ”, μ „μ—­ λ³€μˆ˜λŠ” 물둠이고 μƒμœ„ ν•¨μˆ˜μ—μ„œ μ„ μ–Έν•œ λ³€μˆ˜μ— μ ‘κ·Ό/변경이 κ°€λŠ₯ν•©λ‹ˆλ‹€.

✨ ν•˜μ§€λ§Œ μ§€κΈˆμ€ var 보닀 ES6λΆ€ν„° νƒ„μƒν•œ let, const ν‚€μ›Œλ“œμ˜ μ‚¬μš©μ„±μ΄ λ†’κΈ° λ•Œλ¬Έμ—,
ν•¨μˆ˜ 레벨 μŠ€μ½”ν”„κ°€ μ•„λ‹Œ, 블둝 레벨 μŠ€μ½”ν”„λ‘œ μ΄ν•΄ν•˜κ³  κ³„μ‹œλ©΄ λ©λ‹ˆλ‹€.
ν•˜μ§€λ§Œ, JS의 기초λ₯Ό μœ„ν•΄ λͺ¨λ“  μ˜ˆμ‹œλŠ” var ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ˜€μŠ΅λ‹ˆλ‹€.


쀑첩 μŠ€μ½”ν”„

쀑첩 μŠ€μ½”ν”„λŠ” κ°€μž₯ μΈμ ‘ν•œ 지역을 μš°μ„ ν•˜μ—¬ μ°Έμ‘°ν•©λ‹ˆλ‹€.

var x = 10;

function sushi() {
	var x = 50;
  	console.log(x); // 50
  
  function salad() {
  	x = 100;
    console.log(x); // 100
  };
  
  salad();
};

sushi(); // 100
console.log(x); // 10

ν•¨μˆ˜ sushi μ—μ„œ κ°€μž₯ μΈμ ‘ν•œ x λŠ” λ°”λ‘œ μžκΈ°μžμ‹ μ˜ μ˜μ—­μž…λ‹ˆλ‹€.
ν•¨μˆ˜ salad μ—μ„œ κ°€μž₯ μΈμ ‘ν•œ x λŠ” μƒμœ„ ν•¨μˆ˜ λ‚΄μ˜ xλ₯Ό λ³€κ²½μ‹œν‚¨ 값을 가지고 μžˆλŠ” μžκΈ°μžμ‹ μ˜ μ˜μ—­μž…λ‹ˆλ‹€.
μ „μ—­μ—μ„œμ˜ console.log(x) μ—μ„œ κ°€μž₯ μΈμ ‘ν•œ x λŠ” 전역에 μ„ μ–Έν•œ λ³€μˆ˜μΈ x = 10 μž…λ‹ˆλ‹€.

이처럼 μˆœμ„œλŠ” μžκΈ°μžμ‹ μ˜ local scope -> μžμ‹ μ˜ μƒμœ„ scope μˆœμ„œλ‘œ μ‹λ³„μžλ₯Ό μ°ΎμŠ΅λ‹ˆλ‹€.

또 ν•˜λ‚˜μ˜ 예제λ₯Ό λ³΄κ² μŠ΅λ‹ˆλ‹€.

var sushi = function() {
	var a = 2, b = 3;
  
  	var salad = function() {
    	var b = 10, c = 30;
      	console.log(a += b+c);
    };
  salad();
};

sushi(); // ?

결과값은 뭐라고 좜λ ₯λ κΉŒμš”? πŸ€”
ν•˜λ‚˜μ”© λœ―μ–΄λ΄…μ‹œλ‹€.

var sushi = function() {
	var a = 2, b = 3;
  	// 1번째 지점 : a = 2, b = 3, c = c is not defined
  	var salad = function() {
    	var b = 10, c = 30;
      	// 2번째 지점 : a = 2, b = 10, c = 30
      	console.log(a += b+c);
      	// 3번째 지점 : a = 42, b = 10, c = 30
    };
  // 4번째 지점 : a = 2, b = 3, c = c is not defined
  salad();
  // 5번째 지점 : a = 42, b = 3, c = c is not defined
};

sushi();

JSλŠ” μ‹±κΈ€ μŠ€λ ˆλ“œ λ°©μ‹μœΌλ‘œ ν•œμ€„ ν•œμ€„μ”© μ°¨λ‘€λŒ€λ‘œ 읽어가며 λ™μž‘ν•©λ‹ˆλ‹€.
μ„ μ–Έ μ „, μ„ μ–Έ ν›„, μ‹€ν–‰ μ „, μ‹€ν–‰ ν›„λ§ˆλ‹€ λ³€μˆ˜κ°€ λ³€ν™”ν•˜λŠ” 것듀을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.


⭐️ λ ‰μ‹œμ»¬ μŠ€μ½”ν”„(Lexical Scope)

λ ‰μ‹œμ»¬ μŠ€μ½”ν”„λ₯Ό μ„€λͺ…ν•˜κΈ° μ•žμ„œ, λ¨Όμ € 동적 μŠ€μ½”ν”„μ™€ 정적 μŠ€μ½”ν”„μ— λŒ€ν•΄ κ°„λ‹¨νžˆ μ•Œμ•„λ΄…μ‹œλ‹€.

πŸ’πŸ»β€β™€οΈ 동적 μŠ€μ½”ν”„ (Dynamic Scope)
ν•¨μˆ˜λ₯Ό μ–΄λ””μ„œ 호좜 ν•˜μ˜€λŠ”μ§€μ— 따라 μƒμœ„ μŠ€μ½”ν”„λ₯Ό κ²°μ •

πŸ’πŸ»β€β™€οΈ 정적 μŠ€μ½”ν”„ (Static Scope / Lexical Scope)
ν•¨μˆ˜λ₯Ό μ–΄λ””μ„œ μ„ μ–Έ ν•˜μ˜€λŠ”μ§€μ— 따라 μƒμœ„ μŠ€μ½”ν”„λ₯Ό κ²°μ •

JSλ₯Ό ν¬ν•¨ν•œ λŒ€λΆ€λΆ„μ˜ ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄λŠ” 정적 μŠ€μ½”ν”„, 즉 λ ‰μ‹œμ»¬ μŠ€μ½”ν”„λ₯Ό λ”°λ¦…λ‹ˆλ‹€

λ”°λΌμ„œ, JSλŠ” ν•¨μˆ˜λ₯Ό μ„ μ–Έ ν•œ μ‹œμ μ— 따라 μƒμœ„ μŠ€μ½”ν”„κ°€ κ²°μ •λ©λ‹ˆλ‹€.
이λ₯Ό Lexical Scoping 이라고 λΆ€λ¦…λ‹ˆλ‹€.

var x = 1;

function sushi() {
	var x = 50;
  	salad();
}

function salad() {
	console.log(x);
}

sushi(); // 1
salad(); // 1

μœ„ 예제의 ν•¨μˆ˜ salad 전역에 μ„ μ–Έλ˜μ—ˆμŠ΅λ‹ˆλ‹€.
λ”°λΌμ„œ ν•¨μˆ˜ salad μƒμœ„ μŠ€μ½”ν”„λŠ” 전역이 되고, 전역에 μ„ μ–Έλœ x 값인 1을 좜λ ₯ν•˜κ²Œ λ©λ‹ˆλ‹€.
호좜이 λ˜λŠ” μ‹œμ μ— μŠ€μ½”ν”„κ°€ 결정이 λ˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ—, x 값은 50이 될 수 μ—†μŠ΅λ‹ˆλ‹€.


암묡적 μ „μ—­(Implicit Global)

var x = 10;

function sushi() {
	y = 20;
  	console.log(x + y);
}

sushi(); // 30

ν•¨μˆ˜ sushi μ•ˆμ— μžˆλŠ” y λŠ” μ„ μ–Έλ˜μ§€ μ•Šμ€ λ³€μˆ˜μž…λ‹ˆλ‹€.
κ·ΈλŸ¬λ‚˜ μ°Έμ‘° μ—λŸ¬κ°€ λ°œμƒν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μ„ μ–Έλ˜μ§€ μ•Šμ€ μ‹λ³„μž y κ°€ 마치 μ„ μ–Έλœ λ³€μˆ˜μ²˜λŸΌ λ™μž‘ν•©λ‹ˆλ‹€.
μ΄λŠ” μ„ μ–Έν•˜μ§€ μ•Šμ€ μ‹λ³„μžμ— 값을 ν• λ‹Ήν•˜λ©΄ μ „μ—­ 객체(window)의 ν”„λ‘œνΌν‹°κ°€ 되기 λ•Œλ¬Έμž…λ‹ˆλ‹€.

μ„ μ–Έ ν‚€μ›Œλ“œ(var, let, const)κ°€ 없이 λ³€μˆ˜λ₯Ό μ„ μ–Έν•  경우, μ „μ—­ λ³€μˆ˜λ‘œ μ„ μ–Έλ©λ‹ˆλ‹€.
y = 20 이 window.y = 20 으둜 전역객체 ν”„λ‘œνΌν‹°λ‘œ 동적 생성이 λ˜λŠ” κ²ƒμž…λ‹ˆλ‹€. λ”°λΌμ„œ, 마치 μ „μ—­ λ³€μˆ˜μ²˜λŸΌ λ™μž‘ν•˜κ²Œ λ©λ‹ˆλ‹€.

μ΄λŸ¬ν•œ ν˜„μƒμ„ 암묡적 μ „μ—­(Implicit Global) 이라고 ν•©λ‹ˆλ‹€.

μ•žμ„œ λ§ν–ˆλ“―, μ „μ—­ λ³€μˆ˜λŠ” μ΅œλŒ€ν•œ μ‚¬μš©μ„ 지양해야 ν•˜λ―€λ‘œ,
μ„ μ–Έ ν‚€μ›Œλ“œμ—†μ΄ λ³€μˆ˜λ₯Ό μ΄ˆκΈ°ν™”ν•˜λ©΄ μ•ˆλ©λ‹ˆλ‹€.
ν•¨μˆ˜ λ‚΄μ—μ„œ λ³€μˆ˜λ₯Ό μ„ μ–Έν•  지라도, μ„ μ–Έ ν‚€μ›Œλ“œκ°€ μ—†λ‹€λ©΄ μ „μ—­ λ³€μˆ˜λ‘œ λ™μž‘ν•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

β—οΈκ·ΈλŸ¬λ‚˜ Strict Mode(엄격 λͺ¨λ“œ)λ₯Ό μ‚¬μš©ν•˜λ©΄ JSλŠ” μœ„μ²˜λŸΌ λ¬Έλ²•μ μœΌλ‘œ μ‹€μˆ˜ν•  수 μžˆλŠ” 뢀뢄듀을 μ—λŸ¬λ‘œ νŒλ‹¨ν•΄μ€λ‹ˆλ‹€.

'use strict'

var x = 10;

function sushi() {
	y = 20; // ReferenceError: y is not defined
  	console.log(x + y);
}

sushi();


πŸ™‡πŸΌβ€β™€οΈ μ°Έμ‘°

https://poiemaweb.com/js-scope
https://www.nextree.co.kr/p7363/
https://velog.io/@nittre/JavaScript-ScopeμŠ€μ½”ν”„μ™€-Closureν΄λ‘œμ €-정리
https://hanamon.kr/javascript-μŠ€μ½”ν”„μ™€-λ³€μˆ˜μ„ μ–Έν‚€μ›Œλ“œ-차이점/
https://ljtaek2.tistory.com/140


μ½μ–΄μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€! 큰 도움이 λ˜μ—ˆκΈ°λ₯Ό λ°”λžλ‹ˆλ‹€ πŸͺ„
ν˜Ήμ‹œ 잘λͺ»λœ 정보가 μžˆλ‹€λ©΄, μ•Œλ €μ£Όμ„Έμš”!!
λΉ λ₯Έ μˆ˜μ •ν•˜λ„λ‘ ν•˜κ² μŠ΅λ‹ˆλ‹€ πŸ₯Ή

λ‹€μŒ κ²Œμ‹œλ¬Όμ€,
μŠ€μ½”ν”„ 체인과 κ΄€λ ¨ν•˜μ—¬ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ κ΄€λ ¨ 글을 λ²¨λ‘œκΉ… ν•  μ˜ˆμ •μž…λ‹ˆλ‹€.
그럼 See You ! πŸ‘‹πŸ» ✨

profile
μ“Έλͺ¨μžˆλŠ” 기술자

0개의 λŒ“κΈ€