2.1 파일은 프로그램입니다.
JS에서는 파일 각각이 별도의 프로그램이다.
독립적은 .js 파일 여러개를 하나의 프로그램으로서 작동시키는 유일한 방법은
전역스코프를 사용해 파일 간 상태를 공유하고 공통으로 사용하는 기능을 접근할 수 있도록 만드는 방법 뿐이다.
전역 스코프 (Global Scope)
- 코드 어디서든 접근 가능한 변수 및 함수가 정의되는 범위.
- var는 window(브라우저)나 global(Node.js)에 등록되지만, let과 const는 해당 블록 스코프
JS는 각 모듈을 별도로 처리한다.
파일 하나를 제3의 작고 독립적은 프로그램(파일)과 협력해 전체를 작동시키는 고유한 작은 프로그램이다.
2.2 값
JS에서 값은 크게 원시타입, 객체타입으로 분류 된다.
- 원시 타입 (Primitive Type)
- 값 자체를 저장하며, 변경 불가능 (Immutable).
- Number, String, Boolean, Null, Undefined, Symbol, BigInt 포함.
- 객체 타입 (Object Type)
- 값이 참조로 저장되며, 변경 가능 (Mutable).
- Object, Array, Function, Date, RegExp 등 포함.
문자열 보간(String Interpolation)
문자열 안에 변수를 삽입 하는 방식
let firstName = "카일";
console.log(`제 이름은 ${firstName}입니다.`);
?? 이거 JS에선 템플릿 리터럴 아닌가?
차이점은 이렇다.
✔ 문자열 보간(String Interpolation) 👉 이론적인 개념
✔ 템플릿 리터럴(Template Literal) 👉 구현 방법 (JavaScript 문법)
보간이 필요 없는 경우 따옴표,큰따옴표 한종류만 쓰는 게 좋다.
리터럴이란? (프로그래밍에서 직접 값 자체를 표현해놓은 것)
- 변수를 쓰지 않고 값 자체를 직접 적은 것
- 변수 없이 그냥 적혀있는 숫자,문자열,불리언 값 전부 리터럴
- "hello", 42, true, [1,2,3], { name: "카일" } → 전부 리터럴!
2.2.1 배열과 객체
JS에는 원시 타입 말고 객체 타입도 존재한다.
배열은 객체 내 데이터에 숫자 인덱스가 매겨진다.
var names = ["카일","보라","지수","현"]
names.length; // 4
names[0] // 카일
names[1] // 보라
배열
- 배열에는 원시타입, 객체타입 상관 없이 모든 타입의 값이 들어갈 수 있다.
- 배열안에 배열넣기 가능
- 함수= 값 ⇒ 배열이나 객체의 값에 함수 역시 할당 가능
객체
- 배열보다 좀 더 일반적인 데이터 타입
- 정렬되지 않은 키-값 쌍을 모아놓은 컬렉션
- key(property)를 사용해 인덱스에 접근
var me = {
first : "카일",
last : "심슨" ,
age : 39,
specialties : ["JS", "탁구"]
}
console.log(`제 이름은 ${me.first}입니다.`)
2.2.2 값의 타입
typeof 연산자를 사용해 원시타입 값과 객체타입 값을 구분한다.
console.log(typeof "Hello"); // "string"
console.log(typeof 42); // "number"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null); // ❗"object" (JS의 오래된 버그)
console.log(typeof Symbol("id"));// "symbol"
- type of null은 null이 아닌 object를 반환한다.
- 함수는 function을 반환
- array는 object를 반환
강제 타입 변환
- 의미 : 값의 타입을 변경하는 것
- 예시 : 문자열→ 숫자
2.3 변수 선언과 사용
변수 : 값을 담는 상자
변수를 사용하려면 변수 선언(생성)이 선언 되어야 한다.
키워드 재할당 가능? 재선언 가능? 스코프 호이스팅
var | ✅ 가능 | ✅ 가능 | 함수 스코프 | 호이스팅되지만 초기값 undefined |
let | ✅ 가능 | ❌ 불가능 | 블록 스코프 | 호이스팅되지만 초기화 안 됨 (TDZ) |
const | ❌ 불가능 | ❌ 불가능 | 블록 스코프 | 호이스팅되지만 초기화 안 됨 (TDZ) |
🔥 결론 (언제 뭐 써야 함?)
- var → ❌ (let, const가 더 안전함) 함수 스코프 + window (브라우저) or global (Node.js) 등록됨
let과 const → 블록 스코프(Block Scope)임. window 또는 global에 등록되지 않음
- let → ✅ 값이 변경될 수 있으면 사용 (ex. 반복문, 상태 관리)
- const → ✅ 항상 쓰기! (변경할 필요 없는 값은 const 사용)
var는 선언한 변수가 접근 범위가 함수 스코프다.
let 선언한 변수는 변수 접근범위가 블록이다.
그럼 JS는 이 변수를 3번 읽는 것인가?
→ No. 실제론 2번만 읽는다.
- 실행 컨텍스트 생성 → 변수 & 함수 등록(호이스팅)
- 코드 실행 → 초기화 및 값 할당
- 3단계(선언 → 초기화 → 할당)로 보이는 이유
- let과 const는 선언만 먼저 되고, TDZ를 거친 후 나중에 초기화 & 할당되기 때문!
- TDZ(Temporal Dead Zone)은 "일시적 사각지대" let과 const로 선언된 변수가 호이스팅되긴 하지만, 선언 전에 접근할 수 없는 상태를 의미
2.4 함수
프로시저 : 한번 이상 호출할 수 있고 입력값이 있을 수 있으며 하나 이상의 출력값을 반환하는 구문의 모음
1. 함수 선언문 (Function Declaration)
📌 특징:
- function 키워드로 독립적으로 선언하는 방식.
- 호이스팅(hoisting) 됨 → 선언 전에 호출해도 실행됨.
hello(); // ✅ 가능 (호이스팅됨)
function hello() {
console.log("Hello, 싸장님!");
}
hello(); // "Hello, 싸장님!"
✔️ 정리:
- 함수 선언이 코드 실행 전에 등록되기 때문에, 선언 이전에도 호출 가능!
- 스코프 최상단으로 끌어올려짐(호이스팅).
✅ 2. 함수 표현식 (Function Expression)
📌 특징:
- 함수를 변수에 할당하는 방식.
- 호이스팅 안 됨 → 선언 전에 호출 ❌
greet(); // ❌ TypeError: greet is not a function
const greet = function() {
console.log("안녕하세요!");
};
greet(); // "안녕하세요!"
✔️ 정리:
- 변수에 할당되므로 선언 전에 호출 불가.
- greet는 함수 선언이 아니라 변수에 저장된 값이므로, 초기화 전엔 undefined 상태.
- 즉, 호이스팅되지 않음!
✅ 3. 두 개의 차이점 정리
구분 함수 선언문 함수 표현식
호이스팅 | ✅ O (선언 전에 호출 가능) | ❌ X (선언 전에 호출하면 에러) |
선언 방식 | 독립적으로 선언 | 변수에 할당 |
코드 가독성 | 함수 이름이 바로 보임 | 변수명으로 접근 |
사용 예시 | 일반적인 함수 정의 | 콜백 함수, 클로저 |
함수 표현식으로 선언한 함수가 함수 선언으로 선언한 함수와 다른 점은 함수와 함수 식별자가 코드가 실행되기 전까지는 관계를 맺지 않는다는 점
⇒ 함수표현식으로 선언된 함수는 코드실행 전까지 변수와 연결 안된다.
함수는 오로지 1개의 값만 반환할 수 있다.
여러 개를 반환하고 싶다면 객체 or 배열로 감싸 반환하면 된다.
2.5 비교
2.5.1 같음에 고찰 (같다는 건 무엇인가?)
JS에서 ‘서로 다르지 않음’ 뿐만 아니라 ‘아주 유사’ , ‘교환 가능’한지와 같이 좀 더 넓은 관점에서 비교하는 때도 있다.
JS에서 비교가 일어날 때는 일치 연산자에서처럼 타입도 고려된다.
다른 비교 연산에서는 타입 강제 변환을 허용한다. (42 == ‘42’ true)
✅ 1. ===(일치 비교)는 원시 타입일 때 "값"을 비교
console.log(42 === 42); // ✅ true (숫자 값이 동일)
console.log("hello" === "hello"); // ✅ true (문자열 값이 동일)
- 원시 타입(숫자, 문자열, 불리언 등)은 값을 직접 비교해서 같으면 true.
✅ 2. 객체 비교에서는 "참조(Reference)"를 비교
console.log([1, 2, 3] === [1, 2, 3]); // ❌ false
console.log({ a: 42 } === { a: 42 }); // ❌ false
- 객체는 메모리 주소(참조 값)를 비교하므로, 구조나 내용이 같아도 다르면 false
- 새로운 { a: 42 } 객체는 매번 새로운 메모리 주소를 가지므로 비교 결과가 false.
- ++ 독자성 일치라는 건 - 구조가 아나라 참조(메모리 주소)를 비교한다는 말임.
✅ 3. 같은 참조를 가진 객체끼리는 true
var x = [1, 2, 3];
var y = x; // x를 y에 참조 복사
console.log(y === x); // ✅ true (같은 메모리 주소)
console.log(x === [1, 2, 3]); // ❌ false (새로운 배열)
- y = x; → 배열 참조를 복사해서 y와 x는 같은 주소를 가짐.
- 그러나 [1, 2, 3] 같은 배열을 새로 만들면, 새로운 메모리 주소를 가지므로 false.
✅ 4. JS는 객체의 "구조적 일치(structural equality)"를 비교하지 않음
- JS는 기본적으로 객체의 구조가 같은지 직접 비교하는 기능이 없음.
- "이 객체와 저 객체가 같은지" → 참조가 같은지(reference identity)만 확인 가능.
- 객체의 내용을 비교하려면 직접 코드를 짜야 함.
🔹 예제: 객체 구조가 같은지 비교하려면?
function isEqual(obj1, obj2) {
return JSON.stringify(obj1) === JSON.stringify(obj2);
}
console.log(isEqual({ a: 42 }, { a: 42 })); // ✅ true
console.log(isEqual({ a: 42 }, { a: 43 })); // ❌ false
❗ 하지만 이 방법도 순서가 다를 경우 오작동할 수 있음.
✅ 5. 함수끼리 비교는 더 어렵다
const f1 = function() { return 42; };
const f2 = function() { return 42; };
console.log(f1 === f2); // ❌ false (각각 다른 참조)
- 함수도 객체라서 새로운 함수는 새로운 참조를 가짐.
- 심지어 같은 코드라도 다른 메모리 주소를 가지므로 비교하면 false.
===는 객체의 "내용"이 아닌 "참조 값"을 비교한다
- 원시 타입(number, string, boolean)은 값 자체를 비교.
- 객체({}, [], function)는 메모리 주소(참조 값)를 비교.
- 객체 구조가 같은지 비교하는 기능은 JS에 기본 제공되지 않음.
- 객체 내용 비교는 JSON 변환 같은 추가 코드가 필요함.
- 함수 비교는 더 어려움 → 같은 코드라도 참조가 다르면 false.
2.5.2 강제 변환
타입의 값이 다른 타입의 값으로 변하는 걸 의미한다.
피연산자가 타입이 같으면 완전히 동일하게 작동
1 === 1
1 == 1
그런데 == 연산자는 비교 이전에 강제로 타입을 맞추는 작업을 수행한다는 점에서 ===와 차이가 있다.
- 공통점 : 두 연산자 모두 같은 값 비교
- 다른점 : ==연산자는 타입 강제변환 먼저 실행
그래서 == 연산자는 느슨한 동등 비교연산자가 아닌 강제 변환 동등 비교 연산자라고 설명하는게 적합하다.
42 == "42"; // true
1 == true; // true
다른 연산자는? (<,>,≤,≥)
- 타입이 같은 경우 : ==와 마찬가지로 피연산자들의 타입이 같으면 === 처럼 작동.
- 타입이 다른 경우 : 타입 강제 변환이 먼저 일어남(대개 숫자형으로 변환)
1. 타입이 같은 경우 (==처럼 작동)
→ 타입이 같으면 ===처럼 값 비교만 수행!
console.log(10 > 5); // ✅ true
console.log(3 <= 3); // ✅ true
console.log("apple" < "banana"); // ✅ true (사전순 비교)
console.log(true > false); // ✅ true (true는 1, false는 0으로 변환)
- 숫자끼리는 그대로 크기 비교.
- 문자열끼리는 알파벳 순서(유니코드 순서) 로 비교됨.
- "apple" vs "banana" → "a"가 "b"보다 앞에 있어서 true.
- 불리언 값도 숫자로 변환 (true → 1, false → 0).
2. 타입이 다른 경우 → "숫자형으로 변환" 후 비교
→ == 처럼 타입 강제 변환이 먼저 일어나고, 숫자로 변환한 뒤 비교!
console.log("10" > 2); // ✅ true ("10" → 숫자 10)
console.log("5" < "12"); // ❌ false (문자열 비교 → "5"가 "1"보다 뒤에 있음)
console.log("5" < 12); // ✅ true ("5" → 숫자 5)
console.log(true > 0); // ✅ true (true → 1, false → 0)
console.log(false >= 0); // ✅ true (false → 0)
console.log(null >= 0); // ✅ true (null → 0 변환)
console.log(null > 0); // ❌ false (null → 0 변환 → 0은 0보다 크지 않음)
console.log(undefined > 0); // ❌ false (undefined는 변환 시 NaN → 비교 불가)
console.log(undefined < 0); // ❌ false (undefined → NaN, 비교 불가능)
console.log(undefined == null); // ✅ true (둘 다 "없음"을 의미)
📌 null과 undefined의 비교 주의점!
- null → 숫자 비교(>=, <=)에서는 0으로 변환되지만, == 비교에서는 undefined와 같음.
- undefined → 숫자로 변환 시 NaN이 되므로 모든 크기 비교(>, <, >=, <=)에서 false.
연산자 유형 동작 방식
같은 타입 | ===처럼 값만 비교 |
다른 타입 | 숫자로 변환 후 비교 ("10" > 2 → "10"이 숫자 10으로 변환) |
문자열 비교 | 알파벳 순서(유니코드 순)로 비교 ("5" < "12" → false) |
불리언 값 | true → 1, false → 0 변환 (true > false → 1 > 0) |
null vs 숫자 | null → 0 변환 (null >= 0 → true, null > 0 → false) |
undefined vs 숫자 | undefined는 NaN이 되어 모든 비교에서 false |
비교 연산자(>, <, >=, <=)는 ==처럼 타입 강제 변환을 수행하며, 대부분 숫자로 변환한 후 비교한다!
2.7 코드 구조화 패턴
많은 프로그램이 클래스, 모듈 두가지 패턴을 모두 사용한다.
한 패턴만 고수하는 프로그램도 있고 두패턴 모두 사용하지 않는 프로그램도 있다.
상호 배타적인 패턴이 아니라는 것도 알자.
2.6.1 Class
데이터 + 데이터를 조작하는 함수(메서드)를 묶어서 하나의 객체를 만드는 설계도
Class = 템플릿(객체 + 객체의함수)
// 1. class 이름 { 생성자,함수}
// 2. 변수선언 = new 생성사
// 3. 콘솔로그 변수.함수
class Counter {
constructor() {
this.count = 0;
}
increment() {
this.count++;
}
decrement() {
this.count--;
}
}
const calc = new Calculator();
console.log(calc.add(5, 3)); // ✅ 8
console.log(calc.multiply(5, 3)); // ✅ 15
생성자(constructor)가 없어도 되고, 함수가 없어도 된다.
생성자가 없는 클래스 (constructor 없음)
💡 constructor를 정의하지 않으면, 자동으로 빈 생성자가 추가됨!
class Person {
// 생성자 없음
}
const p = new Person(); // ✅ 정상 동작
console.log(p); // ✅ Person {} (빈 객체)
✔ 생성자가 없어도 기본적으로 객체는 생성됨.
✔ 다만, 속성을 초기화할 방법이 없음!
✔ new Person()을 실행하면, 빈 객체가 만들어짐.
📌 결론:
- 생성자가 없으면 자동으로 빈 constructor()가 추가됨.
- 속성을 초기화할 필요가 없거나, 후에 추가할 경우라면 생략 가능!
메서드가 없는 클래스 (함수 없음)
class Animal {
constructor(type) {
this.type = type;
}
}
const a = new Animal("Dog");
console.log(a.type); // ✅ "Dog"
✔ constructor는 있지만 메서드가 없음.
✔ 객체를 만들고 속성만 저장할 용도라면 메서드 없이도 가능.
✔ 하지만 동작(메서드)을 추가하지 않으면 단순한 데이터 저장용 클래스가 됨.
📌 결론:
- 메서드 없이도 동작하지만, 클래스를 사용하는 의미가 줄어듦.
- 보통 데이터 저장용(모델 클래스) 으로 사용할 때 메서드 없이 만들기도 함.
생성자도 없고 메서드도 없는 클래스
class EmptyClass {}
const obj = new EmptyClass();
console.log(obj); // ✅ EmptyClass {}
✔ 완전 빈 클래스도 가능.
✔ 하지만 이렇게 만들면 객체를 생성할 의미가 거의 없음.
✔ 속성도 없고, 동작(메서드)도 없으므로 사실상 "의미 없는 클래스"가 됨.
클래스 상태 가능 여부 설명
✅ 생성자 없음 | 가능 | 자동으로 빈 constructor()가 추가됨 |
✅ 메서드 없음 | 가능 | 속성만 저장하는 용도로 사용 가능 |
✅ 생성자+메서드 없음 | 가능 | 하지만 사실상 의미 없음 |
확장
클래스 확장은 기존 클래스를 재사용 하면서 새로운 기능을 추가하는 방법이다.
1. 기본
class Animal {
constructor(name) {
this.name = name;
}
makeSound() {
console.log("...");
}
}
// Animal 클래스를 상속받아서 Dog 클래스를 만듦.
class Dog extends Animal {
bark() {
console.log("멍멍!");
}
}
const myDog = new Dog("멍멍이");
console.log(myDog.name); // 멍멍이
myDog.makeSound(); // Animal의 메서드
myDog.bark(); // 멍멍! // Dog에서 추가한 메서드
2. super 키워드로 부모 클래스 생성자 호출
super란?
- 부모 클래스의 constructor(생성자) 호출
- 부모 클래스의 메서드 실행
- ⇒ extends 없이 super를 쓰면 에러가 난다.
class Animal {
constructor(name) {
this.name = name;
}
}
class Cat extends Animal {
constructor(name, color) {
super(name); // ✅ 부모 클래스(Animal)의 생성자 호출
this.color = color;
}
meow() {
console.log("Meow! 🐱");
}
}
const myCat = new Cat("Whiskers", "Gray");
console.log(myCat.name); // ✅ "Whiskers" (Animal에서 상속됨)
console.log(myCat.color); // ✅ "Gray" (Cat에서 추가된 속성)
myCat.meow(); // ✅ "Meow! 🐱"
3. 부모 매서드 오버라이딩(재정의)
부모 클래스의 매서드를 자식 클래스에서 다른 동작으로 변경 가능하다.
class Animal {
makeSound() {
console.log("Some generic animal sound...");
}
}
class Dog extends Animal {
makeSound() { // ✅ 부모 메서드 오버라이딩(재정의)
console.log("Bark! 🐶");
}
}
const myDog = new Dog();
myDog.makeSound(); // ✅ "Bark! 🐶" (부모 메서드가 덮어씌워짐)
4. 부모 메서드 + 새로운 기능 추가 (super.method)
class Animal {
makeSound() {
console.log("Some generic animal sound...");
}
}
class Bird extends Animal {
makeSound() {
super.makeSound(); // ✅ 부모의 메서드 먼저 실행
console.log("Tweet! 🐦");
}
}
const myBird = new Bird();
myBird.makeSound();
/*
✅ 출력:
Some generic animal sound...
Tweet! 🐦
*/
2.6.2 모듈
코드의 일부를 독립적인 파일로 분리하여 관리하는 개념이다.
ES6에서 추가 (import , export)
모듈의 장점
- 코드의 재사용 가능 → 한번 만든 모듈을 여러 곳에서 가져다 쓸 수 있음.
- 코드 유지보수 용이 → 기능별로 파일을 분리하면 관리가 쉬워짐
- 네임 스페이스 관리 → 전역 변수를 피하고 모듈 내에서만 유지 가능
모듈을 export로 내보내기
export function add(a, b) {
return a + b;
}
export const PI = 3.14159;
모듈 import 가져오기
// main.js
import { add, PI } from './math.js';
console.log(add(2, 3)); // ✅ 5
console.log(PI); // ✅ 3.14159
클래스 모듈이란?
ES6 이전에 사용되던 모듈 시스템을 의미한다.
JS 자체적으로 모듈 시스템이 없었기 때문에 , 함수나 즉시 실행 함수(IIFE)를 활용해서 모듈을 구현 했다.
var MathModule = {
add: function(a,b) {
return a + b;
},
PI: 3.14159
};
console.log(MathModule.add(2, 3)); // ✅ 5
console.log(MathModule.PI); // ✅ 3.14159
✔ 객체(MathModule)를 만들어서 전역에서 공유하는 방식.
✔ 단점: 모든 모듈이 전역에 노출됨 → 이름 충돌 가능성 있음!
즉시 실행 함수(IIFE, Immediately Invoked Function Expression)
var MathModule = (function() {
var PI = 3.14159; // private 변수 (외부에서 접근 불가)
function add(a, b) {
return a + b;
}
return {
add: add,
getPI: function() { return PI; } // 접근 가능하게 메서드 추가
};
})();
console.log(MathModule.add(2, 3)); // ✅ 5
console.log(MathModule.getPI()); // ✅ 3.14159
console.log(MathModule.PI); // ❌ undefined (private 변수)
✔ 즉시 실행 함수(IIFE)를 사용하여 변수 보호 가능!
✔ PI는 외부에서 직접 접근할 수 없음 → 캡슐화 가능! → ?? var인데 왜 그러지? ⇒
- 자체적 특성 var는 함수 스코프를 존중하기 때문에 함수 안에서 정의하면 외부에서 그 var 변수를 참조할 수 없다.
- 즉시 실행함수(IIFE) 내부의 var는 클로저로 보호 됨 var가 선언 된 곳은 함수 스코프가 만들어져서 다른 곳에선 참조할 수 없다.
모듈 팩토리
1. 기본적인 모듈 팩토리 패턴
✅ 함수가 새로운 객체(모듈)를 반환하는 구조
function createUser(name, age) {
return {
name: name,
age: age,
greet: function() {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
}
};
}
const user1 = createUser("Minho", 28);
const user2 = createUser("Alice", 25);
user1.greet(); // ✅ "Hello, my name is Minho and I am 28 years old."
user2.greet(); // ✅ "Hello, my name is Alice and I am 25 years old."
✔ createUser() 함수가 객체를 반환하는 모듈 팩토리 역할을 함.
✔ 함수 호출할 때마다 새로운 객체가 생성됨.
2. 모듈 팩토리를 활용한 클로저(정보 은닉)
function createCounter() {
let count = 0; // private 변수
return {
increment: function() {
count++;
console.log(`Count: ${count}`);
},
decrement: function() {
count--;
console.log(`Count: ${count}`);
},
getCount: function() {
return count;
}
};
}
const counter1 = createCounter();
const counter2 = createCounter();
counter1.increment(); // ✅ Count: 1
counter1.increment(); // ✅ Count: 2
console.log(counter1.getCount()); // ✅ 2
counter2.increment(); // ✅ Count: 1 (새로운 모듈이므로 값이 독립적)
console.log(counter2.getCount()); // ✅ 1
✔ count는 외부에서 직접 접근할 수 없는 private 변수!
✔ createCounter()를 호출할 때마다 독립적인 상태를 가진 새로운 객체가 생성됨.
✔ 즉, 각 counter는 서로 다른 count 값을 유지할 수 있음.
3. 즉시 실행 함수(IIFE)와 함께 사용하기
const MathModule = (function() {
function createMathModule() {
return {
add: (a, b) => a + b,
multiply: (a, b) => a * b
};
}
return createMathModule();
})();
console.log(MathModule.add(3, 5)); // ✅ 8
console.log(MathModule.multiply(3, 5)); // ✅ 15
✔ createMathModule() 함수가 모듈을 생성하는 역할을 함.
✔ 즉시 실행 함수(IIFE)를 사용하면 단 한 번만 실행되어 고정된 모듈을 제공할 수 있음.
4. 모듈 팩토리를 활용한 require() 방식 (CommonJS)
Node.js의 CommonJS 모듈 시스템에서도 모듈 팩토리를 사용할 수 있음.
// math.js
module.exports = function() {
return {
add: (a, b) => a + b,
multiply: (a, b) => a * b
};
};
// main.js
const createMathModule = require('./math');
const MathModule = createMathModule();
console.log(MathModule.add(4, 6)); // ✅ 10
console.log(MathModule.multiply(4, 6)); // ✅ 24
✔ require()를 호출할 때마다 새로운 모듈이 생성됨.
✔ 즉, 각 호출마다 새로운 상태를 가지는 모듈을 만들 수 있음.
🚀 모듈 팩토리 정리
개념 설명 예제
✅ 모듈 팩토리 | 함수를 사용하여 동적으로 모듈을 생성 | function createUser() { return { ... }; } |
✅ 클로저 활용 | 내부 상태(변수)를 보호하면서 객체 생성 | function createCounter() { let count = 0; return { increment() { count++; } }; } |
✅ 즉시 실행 함수(IIFE)와 결합 | 한 번만 실행되도록 설정 | const Module = (function() { return { ... }; })(); |
✅ Node.js CommonJS | require()를 호출할 때마다 새로운 모듈 생성 | module.exports = function() { return { ... }; }; |
📌 한 줄 요약:
"모듈 팩토리는 함수를 사용하여 새로운 모듈(객체)을 동적으로 생성하는 패턴이다!"
'Study > JavaScript' 카테고리의 다른 글
You don't know JS yet(1.5~1.8) (0) | 2025.01.23 |
---|---|
You don't know JS (1.1~1.4) (0) | 2025.01.16 |