본문으둜 κ±΄λ„ˆλ›°κΈ°

[Medium] πŸ“„ Primitive vs Reference Types

1. What are Primitive Types and Reference Types?​

μ›μ‹œ νƒ€μž…(Primitive Types)κ³Ό μ°Έμ‘° νƒ€μž…(Reference Types)μ΄λž€ 무엇인가?

JavaScript의 데이터 νƒ€μž…μ€ μ›μ‹œ νƒ€μž…κ³Ό μ°Έμ‘° νƒ€μž… 두 κ°€μ§€λ‘œ λ‚˜λ‰©λ‹ˆλ‹€. λ©”λͺ¨λ¦¬ μ €μž₯ 방식과 전달 λ™μž‘μ— 본질적인 차이가 μžˆμŠ΅λ‹ˆλ‹€.

μ›μ‹œ νƒ€μž…(Primitive Types)​

νŠΉμ§•:

  • **μŠ€νƒ(Stack)**에 μ €μž₯
  • 전달 μ‹œ κ°’ 자체λ₯Ό 볡사(Call by Value)
  • λΆˆλ³€(Immutable)

7κ°€μ§€ μ’…λ₯˜:

// 1. String(λ¬Έμžμ—΄)
const str = 'hello';

// 2. Number(숫자)
const num = 42;

// 3. Boolean(λΆˆλ¦¬μ–Έ)
const bool = true;

// 4. Undefined
let undef;

// 5. Null
const n = null;

// 6. Symbol(ES6)
const sym = Symbol('unique');

// 7. BigInt(ES2020)
const bigInt = 9007199254740991n;

μ°Έμ‘° νƒ€μž…(Reference Types)​

νŠΉμ§•:

  • **νž™(Heap)**에 μ €μž₯
  • 전달 μ‹œ μ°Έμ‘°(λ©”λͺ¨λ¦¬ μ£Όμ†Œ)λ₯Ό 볡사(Call by Reference)
  • κ°€λ³€(Mutable)

μ’…λ₯˜:

// 1. Object(객체)
const obj = { name: 'John' };

// 2. Array(λ°°μ—΄)
const arr = [1, 2, 3];

// 3. Function(ν•¨μˆ˜)
const func = function () {};

// 4. Date
const date = new Date();

// 5. RegExp
const regex = /abc/;

// 6. Map, Set, WeakMap, WeakSet (ES6)
const map = new Map();
const set = new Set();

2. Call by Value vs Call by Reference​

값에 μ˜ν•œ 전달(Call by Value) vs 참쑰에 μ˜ν•œ 전달(Call by Reference)

값에 μ˜ν•œ 전달(Call by Value) - μ›μ‹œ νƒ€μž…β€‹

λ™μž‘: κ°’ 자체λ₯Ό λ³΅μ‚¬ν•˜λ©°, 볡사본을 μˆ˜μ •ν•΄λ„ μ›λž˜ 값에 영ν–₯을 μ£Όμ§€ μ•ŠλŠ”λ‹€.

// μ›μ‹œ νƒ€μž…: κ°’ 전달
let a = 10;
let b = a; // κ°’ 볡사

b = 20; // b μˆ˜μ •

console.log(a); // 10 (영ν–₯ μ—†μŒ)
console.log(b); // 20

λ©”λͺ¨λ¦¬ λ‹€μ΄μ–΄κ·Έλž¨:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Stack β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ a: 10 β”‚ ← 독립적인 κ°’
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ b: 20 β”‚ ← 독립적인 κ°’ (볡사 ν›„ μˆ˜μ •)
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

참쑰에 μ˜ν•œ 전달(Call by Reference) - μ°Έμ‘° νƒ€μž…β€‹

λ™μž‘: λ©”λͺ¨λ¦¬ μ£Όμ†Œλ₯Ό λ³΅μ‚¬ν•˜λ©°, 두 λ³€μˆ˜κ°€ 같은 객체λ₯Ό 가리킨닀.

// μ°Έμ‘° νƒ€μž…: μ°Έμ‘° 전달
let obj1 = { name: 'John' };
let obj2 = obj1; // λ©”λͺ¨λ¦¬ μ£Όμ†Œ 볡사

obj2.name = 'Jane'; // obj2λ₯Ό 톡해 μˆ˜μ •

console.log(obj1.name); // 'Jane' (영ν–₯ λ°›μŒ!)
console.log(obj2.name); // 'Jane'
console.log(obj1 === obj2); // true (같은 객체λ₯Ό 가리킴)

λ©”λͺ¨λ¦¬ λ‹€μ΄μ–΄κ·Έλž¨:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Stack β”‚ β”‚ Heap β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ obj1 ───┼───────────────────>β”‚ { name: 'Jane' } β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚
β”‚ obj2 ───┼───────────────────>β”‚ (같은 객체) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

3. Common Quiz Questions​

자주 λ‚˜μ˜€λŠ” ν€΄μ¦ˆ 문제

문제 1: μ›μ‹œ νƒ€μž…μ˜ 전달​

function changeValue(x) {
x = 100;
console.log('ν•¨μˆ˜ λ‚΄ x:', x);
}

let num = 50;
changeValue(num);
console.log('ν•¨μˆ˜ μ™Έ num:', num);
ν΄λ¦­ν•˜μ—¬ λ‹΅ 보기
// ν•¨μˆ˜ λ‚΄ x: 100
// ν•¨μˆ˜ μ™Έ num: 50

μ„€λͺ…:

  • num은 μ›μ‹œ νƒ€μž…(Number)
  • ν•¨μˆ˜μ— 전달할 λ•Œ 값을 λ³΅μ‚¬ν•˜λ―€λ‘œ, x와 num은 독립적인 λ³€μˆ˜
  • xλ₯Ό μˆ˜μ •ν•΄λ„ num에 영ν–₯을 μ£Όμ§€ μ•ŠμŒ
// μ‹€ν–‰ 흐름
let num = 50; // Stack: num = 50
changeValue(num); // Stack: x = 50 (볡사)
x = 100; // Stack: x = 100 (x만 μˆ˜μ •)
console.log(num); // Stack: num = 50 (영ν–₯ μ—†μŒ)

문제 2: μ°Έμ‘° νƒ€μž…μ˜ 전달​

function changeObject(obj) {
obj.name = 'Changed';
console.log('ν•¨μˆ˜ λ‚΄ obj.name:', obj.name);
}

let person = { name: 'Original' };
changeObject(person);
console.log('ν•¨μˆ˜ μ™Έ person.name:', person.name);
ν΄λ¦­ν•˜μ—¬ λ‹΅ 보기
// ν•¨μˆ˜ λ‚΄ obj.name: Changed
// ν•¨μˆ˜ μ™Έ person.name: Changed

μ„€λͺ…:

  • person은 μ°Έμ‘° νƒ€μž…(Object)
  • ν•¨μˆ˜μ— 전달할 λ•Œ λ©”λͺ¨λ¦¬ μ£Όμ†Œλ₯Ό 볡사
  • obj와 person은 같은 객체λ₯Ό 가리킴
  • objλ₯Ό 톡해 객체 λ‚΄μš©μ„ μˆ˜μ •ν•˜λ©΄ person도 영ν–₯을 λ°›μŒ
// λ©”λͺ¨λ¦¬ λ‹€μ΄μ–΄κ·Έλž¨
let person = { name: 'Original' }; // Heap: 객체 생성 @0x001
changeObject(person); // Stack: obj = @0x001 (μ£Όμ†Œ 볡사)
obj.name = 'Changed'; // Heap: @0x001.name = 'Changed'
console.log(person.name); // Heap: @0x001.name (같은 객체)

문제 3: μž¬ν• λ‹Ή vs 속성 μˆ˜μ •β€‹

function test1(obj) {
obj.name = 'Modified'; // 속성 μˆ˜μ •
}

function test2(obj) {
obj = { name: 'New Object' }; // μž¬ν• λ‹Ή
}

let person = { name: 'Original' };

test1(person);
console.log('A:', person.name);

test2(person);
console.log('B:', person.name);
ν΄λ¦­ν•˜μ—¬ λ‹΅ 보기
// A: Modified
// B: Modified ('New Object'κ°€ μ•„λ‹˜!)

μ„€λͺ…:

test1: 속성 μˆ˜μ •

function test1(obj) {
obj.name = 'Modified'; // βœ… μ›λž˜ 객체의 속성을 μˆ˜μ •
}
// personκ³Ό objλŠ” 같은 객체λ₯Ό κ°€λ¦¬ν‚€λ―€λ‘œ μˆ˜μ •λ¨

test2: μž¬ν• λ‹Ή

function test2(obj) {
obj = { name: 'New Object' }; // ❌ obj의 참쑰만 λ³€κ²½
}
// objλŠ” 이제 μƒˆ 객체λ₯Ό κ°€λ¦¬ν‚€μ§€λ§Œ, person은 μ—¬μ „νžˆ μ›λž˜ 객체λ₯Ό 가리킴

λ©”λͺ¨λ¦¬ λ‹€μ΄μ–΄κ·Έλž¨:

// test1 이전
person ────> { name: 'Original' }
obj ────> { name: 'Original' } (같은 것)

// test1 이후
person ────> { name: 'Modified' }
obj ────> { name: 'Modified' } (같은 것)

// test2 μ‹€ν–‰
person ────> { name: 'Modified' } (λ³€κ²½ μ—†μŒ)
obj ────> { name: 'New Object' } (μƒˆ 객체)

// test2 μ’…λ£Œ ν›„
person ────> { name: 'Modified' } (μ—¬μ „νžˆ λ³€κ²½ μ—†μŒ)
// objλŠ” μ†Œλ©Έλ˜κ³ , μƒˆ κ°μ²΄λŠ” κ°€λΉ„μ§€ μ»¬λ ‰μ…˜λ¨

문제 4: λ°°μ—΄μ˜ 전달​

function modifyArray(arr) {
arr.push(4);
console.log('1:', arr);
}

function reassignArray(arr) {
arr = [5, 6, 7];
console.log('2:', arr);
}

let numbers = [1, 2, 3];
modifyArray(numbers);
console.log('3:', numbers);

reassignArray(numbers);
console.log('4:', numbers);
ν΄λ¦­ν•˜μ—¬ λ‹΅ 보기
// 1: [1, 2, 3, 4]
// 3: [1, 2, 3, 4]
// 2: [5, 6, 7]
// 4: [1, 2, 3, 4]

μ„€λͺ…:

  • modifyArray: μ›λž˜ λ°°μ—΄μ˜ λ‚΄μš©μ„ μˆ˜μ •ν•˜λ―€λ‘œ numbersκ°€ 영ν–₯을 λ°›μŒ
  • reassignArray: λ§€κ°œλ³€μˆ˜μ˜ 참쑰만 λ³€κ²½ν•˜λ―€λ‘œ numbersλŠ” 영ν–₯ μ—†μŒ

문제 5: 비ꡐ 연산​

// μ›μ‹œ νƒ€μž… 비ꡐ
let a = 10;
let b = 10;
console.log('A:', a === b);

// μ°Έμ‘° νƒ€μž… 비ꡐ
let obj1 = { value: 10 };
let obj2 = { value: 10 };
let obj3 = obj1;
console.log('B:', obj1 === obj2);
console.log('C:', obj1 === obj3);
ν΄λ¦­ν•˜μ—¬ λ‹΅ 보기
// A: true
// B: false
// C: true

μ„€λͺ…:

μ›μ‹œ νƒ€μž…: 값을 비ꡐ

10 === 10; // true (값이 동일)

μ°Έμ‘° νƒ€μž…: λ©”λͺ¨λ¦¬ μ£Όμ†Œλ₯Ό 비ꡐ

obj1 === obj2; // false (λ‹€λ₯Έ 객체, λ‹€λ₯Έ μ£Όμ†Œ)
obj1 === obj3; // true (같은 객체λ₯Ό 가리킴)

λ©”λͺ¨λ¦¬ λ‹€μ΄μ–΄κ·Έλž¨:

obj1 ────> @0x001: { value: 10 }
obj2 ────> @0x002: { value: 10 } (λ‚΄μš©μ€ κ°™μ§€λ§Œ μ£Όμ†Œκ°€ 닀름)
obj3 ────> @0x001: { value: 10 } (obj1κ³Ό 같은 μ£Όμ†Œ)

4. Shallow Copy vs Deep Copy​

얕은 볡사 vs κΉŠμ€ 볡사

얕은 볡사(Shallow Copy)​

μ •μ˜: 첫 번째 λ‹¨κ³„λ§Œ λ³΅μ‚¬ν•˜λ©°, μ€‘μ²©λœ κ°μ²΄λŠ” μ—¬μ „νžˆ μ°Έμ‘° μƒνƒœμ΄λ‹€.

방법 1: μ „κ°œ μ—°μ‚°μž(Spread Operator)​

const original = {
name: 'John',
address: { city: 'Taipei' },
};

const copy = { ...original };

// 첫 번째 단계 μˆ˜μ •: μ›λž˜ 객체에 영ν–₯ μ—†μŒ
copy.name = 'Jane';
console.log(original.name); // 'John' (영ν–₯ μ—†μŒ)

// 쀑첩 객체 μˆ˜μ •: μ›λž˜ 객체에 영ν–₯!
copy.address.city = 'Kaohsiung';
console.log(original.address.city); // 'Kaohsiung' (영ν–₯ λ°›μŒ!)

방법 2: Object.assign()​

const original = { name: 'John', age: 30 };
const copy = Object.assign({}, original);

copy.name = 'Jane';
console.log(original.name); // 'John' (영ν–₯ μ—†μŒ)

방법 3: λ°°μ—΄μ˜ 얕은 볡사​

const arr1 = [1, 2, 3];

// 방법 1: μ „κ°œ μ—°μ‚°μž
const arr2 = [...arr1];

// 방법 2: slice()
const arr3 = arr1.slice();

// 방법 3: Array.from()
const arr4 = Array.from(arr1);

arr2[0] = 999;
console.log(arr1[0]); // 1 (영ν–₯ μ—†μŒ)

κΉŠμ€ 볡사(Deep Copy)​

μ •μ˜: μ€‘μ²©λœ 객체λ₯Ό ν¬ν•¨ν•œ λͺ¨λ“  단계λ₯Ό μ™„μ „νžˆ λ³΅μ‚¬ν•œλ‹€.

방법 1: JSON.parse + JSON.stringify (κ°€μž₯ 일반적)​

const original = {
name: 'John',
address: { city: 'Taipei' },
hobbies: ['reading', 'gaming'],
};

const copy = JSON.parse(JSON.stringify(original));

// 쀑첩 객체 μˆ˜μ •: μ›λž˜ 객체에 영ν–₯ μ—†μŒ
copy.address.city = 'Kaohsiung';
console.log(original.address.city); // 'Taipei' (영ν–₯ μ—†μŒ)

copy.hobbies.push('coding');
console.log(original.hobbies); // ['reading', 'gaming'] (영ν–₯ μ—†μŒ)

μ œν•œμ‚¬ν•­:

const obj = {
date: new Date(), // ❌ λ¬Έμžμ—΄λ‘œ λ³€ν™˜λ¨
func: () => {}, // ❌ λ¬΄μ‹œλ¨
undef: undefined, // ❌ λ¬΄μ‹œλ¨
symbol: Symbol('test'), // ❌ λ¬΄μ‹œλ¨
regexp: /abc/, // ❌ {}둜 λ³€ν™˜λ¨
circular: null, // ❌ μˆœν™˜ μ°Έμ‘° μ‹œ μ—λŸ¬ λ°œμƒ
};
obj.circular = obj; // μˆœν™˜ μ°Έμ‘°

JSON.parse(JSON.stringify(obj)); // μ—λŸ¬ λ˜λŠ” 데이터 손싀

방법 2: structuredClone() (λͺ¨λ˜ λΈŒλΌμš°μ €)​

const original = {
name: 'John',
address: { city: 'Taipei' },
date: new Date(),
};

const copy = structuredClone(original);

// Date λ“± 특수 객체도 μ •ν™•ν•˜κ²Œ 볡사 κ°€λŠ₯
console.log(copy.date instanceof Date); // true

μž₯점:

  • βœ… Date, RegExp, Map, Set λ“± 지원
  • βœ… μˆœν™˜ μ°Έμ‘° 지원
  • βœ… μ„±λŠ₯이 μ’‹μŒ

μ œν•œμ‚¬ν•­:

  • ❌ ν•¨μˆ˜ 미지원
  • ❌ Symbol 미지원

방법 3: μž¬κ·€λ‘œ κΉŠμ€ 볡사 κ΅¬ν˜„β€‹

function deepClone(obj) {
// nullκ³Ό 비객체 처리
if (obj === null || typeof obj !== 'object') {
return obj;
}

// λ°°μ—΄ 처리
if (Array.isArray(obj)) {
return obj.map((item) => deepClone(item));
}

// Date 처리
if (obj instanceof Date) {
return new Date(obj);
}

// RegExp 처리
if (obj instanceof RegExp) {
return new RegExp(obj);
}

// 객체 처리
const cloned = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
cloned[key] = deepClone(obj[key]);
}
}

return cloned;
}

// μ‚¬μš© μ˜ˆμ‹œ
const original = {
name: 'John',
address: { city: 'Taipei' },
hobbies: ['reading'],
date: new Date(),
};

const copy = deepClone(original);
copy.address.city = 'Kaohsiung';
console.log(original.address.city); // 'Taipei' (영ν–₯ μ—†μŒ)

방법 4: Lodash μ‚¬μš©β€‹

import _ from 'lodash';

const original = {
name: 'John',
address: { city: 'Taipei' },
};

const copy = _.cloneDeep(original);

얕은 볡사 vs κΉŠμ€ 볡사 비ꡐ​

νŠΉμ„±μ–•μ€ λ³΅μ‚¬κΉŠμ€ 볡사
볡사 단계첫 번째 λ‹¨κ³„λ§Œλͺ¨λ“  단계
쀑첩 κ°μ²΄μ—¬μ „νžˆ μ°Έμ‘°μ™„μ „νžˆ 독립
μ„±λŠ₯λΉ λ¦„λŠλ¦Ό
λ©”λͺ¨λ¦¬μ μŒλ§ŽμŒ
μ‚¬μš© μ‹œλ‚˜λ¦¬μ˜€λ‹¨μˆœν•œ κ°μ²΄λ³΅μž‘ν•œ 쀑첩 ꡬ쑰

5. Common Pitfalls​

ν”ν•œ 함정

함정 1: λ§€κ°œλ³€μˆ˜ μ „λ‹¬λ‘œ μ›μ‹œ νƒ€μž…μ„ λ³€κ²½ν•  수 μžˆλ‹€κ³  착각​

// ❌ 잘λͺ»λœ 이해
function increment(num) {
num = num + 1;
return num;
}

let count = 5;
increment(count);
console.log(count); // 5 (6이 λ˜μ§€ μ•ŠμŒ!)

// βœ… μ˜¬λ°”λ₯Έ μž‘μ„±λ²•
count = increment(count); // λ°˜ν™˜κ°’μ„ λ°›μ•„μ•Ό 함
console.log(count); // 6

함정 2: μž¬ν• λ‹ΉμœΌλ‘œ μ™ΈλΆ€ 객체λ₯Ό λ³€κ²½ν•  수 μžˆλ‹€κ³  착각​

// ❌ 잘λͺ»λœ 이해
function resetObject(obj) {
obj = { name: 'Reset' }; // λ§€κ°œλ³€μˆ˜μ˜ 참쑰만 λ³€κ²½
}

let person = { name: 'Original' };
resetObject(person);
console.log(person.name); // 'Original' (λ¦¬μ…‹λ˜μ§€ μ•ŠμŒ!)

// βœ… μ˜¬λ°”λ₯Έ μž‘μ„±λ²• 1: 속성 μˆ˜μ •
function resetObject(obj) {
obj.name = 'Reset';
}

// βœ… μ˜¬λ°”λ₯Έ μž‘μ„±λ²• 2: μƒˆ 객체 λ°˜ν™˜
function resetObject(obj) {
return { name: 'Reset' };
}
person = resetObject(person);

함정 3: μ „κ°œ μ—°μ‚°μžκ°€ κΉŠμ€ 볡사라고 착각​

// ❌ 잘λͺ»λœ 이해
const original = {
user: { name: 'John' },
};

const copy = { ...original }; // 얕은 볡사!

copy.user.name = 'Jane';
console.log(original.user.name); // 'Jane' (영ν–₯ λ°›μŒ!)

// βœ… μ˜¬λ°”λ₯Έ μž‘μ„±λ²•: κΉŠμ€ 볡사
const copy = JSON.parse(JSON.stringify(original));
// λ˜λŠ”
const copy = structuredClone(original);

함정 4: const에 λŒ€ν•œ μ˜€ν•΄β€‹

// constλŠ” μž¬ν• λ‹Ήλ§Œ μ•ˆ λ˜λŠ” 것이지, λΆˆλ³€μ΄ μ•„λ‹˜!

const obj = { name: 'John' };

// ❌ μž¬ν• λ‹Ή λΆˆκ°€
obj = { name: 'Jane' }; // TypeError: Assignment to constant variable

// βœ… 속성 μˆ˜μ • κ°€λŠ₯
obj.name = 'Jane'; // 정상 λ™μž‘
obj.age = 30; // 정상 λ™μž‘

// μ§„μ •ν•œ λΆˆλ³€μ„ μ›ν•œλ‹€λ©΄
const immutableObj = Object.freeze({ name: 'John' });
immutableObj.name = 'Jane'; // 쑰용히 μ‹€νŒ¨ (strict λͺ¨λ“œμ—μ„œλŠ” μ—λŸ¬)
console.log(immutableObj.name); // 'John' (μˆ˜μ •λ˜μ§€ μ•ŠμŒ)

함정 5: 루프 λ‚΄ μ°Έμ‘° λ¬Έμ œβ€‹

// ❌ ν”ν•œ μ‹€μˆ˜
const arr = [];
const obj = { value: 0 };

for (let i = 0; i < 3; i++) {
obj.value = i;
arr.push(obj); // λͺ¨λ‘ 같은 객체λ₯Ό 가리킴!
}

console.log(arr);
// [{ value: 2 }, { value: 2 }, { value: 2 }]
// λͺ¨λ‘ 같은 객체이며 μ΅œμ’…κ°’μ€ μ „λΆ€ 2

// βœ… μ˜¬λ°”λ₯Έ μž‘μ„±λ²•: 맀번 μƒˆ 객체 생성
const arr = [];

for (let i = 0; i < 3; i++) {
arr.push({ value: i }); // 맀번 μƒˆ 객체 생성
}

console.log(arr);
// [{ value: 0 }, { value: 1 }, { value: 2 }]

6. Best Practices​

λͺ¨λ²” 사둀

βœ… ꢌμž₯ 방법​

// 1. 객체λ₯Ό 볡사할 λ•Œ λͺ…μ‹œμ μœΌλ‘œ 볡사 방법 μ‚¬μš©
const original = { name: 'John', age: 30 };

// 얕은 볡사 (λ‹¨μˆœν•œ 객체)
const copy1 = { ...original };

// κΉŠμ€ 볡사 (쀑첩 객체)
const copy2 = structuredClone(original);

// 2. ν•¨μˆ˜μ—μ„œ λΆ€μž‘μš©μœΌλ‘œ λ§€κ°œλ³€μˆ˜λ₯Ό μˆ˜μ •ν•˜μ§€ μ•ŠκΈ°
// ❌ λ‚˜μ¨
function addItem(arr, item) {
arr.push(item); // μ›λž˜ λ°°μ—΄ μˆ˜μ •
}

// βœ… μ’‹μŒ
function addItem(arr, item) {
return [...arr, item]; // μƒˆ λ°°μ—΄ λ°˜ν™˜
}

// 3. constλ₯Ό μ‚¬μš©ν•˜μ—¬ μ˜λ„μΉ˜ μ•Šμ€ μž¬ν• λ‹Ή λ°©μ§€
const config = { theme: 'dark' };
// config = {}; // μ—λŸ¬ λ°œμƒ

// 4. λΆˆλ³€ 객체가 ν•„μš”ν•  λ•Œ Object.freeze μ‚¬μš©
const constants = Object.freeze({
PI: 3.14159,
MAX_SIZE: 100,
});

❌ ν”Όν•΄μ•Ό ν•  방법​

// 1. λ§€κ°œλ³€μˆ˜ μ „λ‹¬λ‘œ μ›μ‹œ νƒ€μž…μ„ μˆ˜μ •ν•˜λ € ν•˜μ§€ μ•ŠκΈ°
function increment(num) {
num++; // ❌ 효과 μ—†μŒ
}

// 2. 얕은 볡사와 κΉŠμ€ 볡사λ₯Ό ν˜Όλ™ν•˜μ§€ μ•ŠκΈ°
const copy = { ...nested }; // ❌ κΉŠμ€ 볡사라고 착각

// 3. λ£¨ν”„μ—μ„œ 같은 객체 μ°Έμ‘°λ₯Ό 반볡 μ‚¬μš©ν•˜μ§€ μ•ŠκΈ°
for (let i = 0; i < 3; i++) {
arr.push(obj); // ❌ λͺ¨λ‘ 같은 객체λ₯Ό 가리킴
}

7. Interview Summary​

λ©΄μ ‘ μš”μ•½

λΉ λ₯Έ 암기​

μ›μ‹œ νƒ€μž…(Primitive):

  • String, Number, Boolean, Undefined, Null, Symbol, BigInt
  • κ°’ 전달(Call by Value)
  • Stack에 μ €μž₯
  • λΆˆλ³€(Immutable)

μ°Έμ‘° νƒ€μž…(Reference):

  • Object, Array, Function, Date, RegExp, etc.
  • μ°Έμ‘° 전달(Call by Reference)
  • Heap에 μ €μž₯
  • κ°€λ³€(Mutable)

λ©΄μ ‘ λ‹΅λ³€ μ˜ˆμ‹œβ€‹

Q: JavaScriptλŠ” Call by Value인가 Call by Reference인가?

JavaScriptλŠ” λͺ¨λ“  νƒ€μž…μ— λŒ€ν•΄ Call by Valueμ΄μ§€λ§Œ, μ°Έμ‘° νƒ€μž…μ΄ μ „λ‹¬ν•˜λŠ” "κ°’"은 λ©”λͺ¨λ¦¬ μ£Όμ†Œμž…λ‹ˆλ‹€.

  • μ›μ‹œ νƒ€μž…: κ°’μ˜ 볡사본을 μ „λ‹¬ν•˜λ―€λ‘œ μˆ˜μ •ν•΄λ„ μ›λž˜ 값에 영ν–₯ μ—†μŒ
  • μ°Έμ‘° νƒ€μž…: μ£Όμ†Œμ˜ 볡사본을 μ „λ‹¬ν•˜λ―€λ‘œ μ£Όμ†Œλ₯Ό 톡해 μ›λž˜ 객체λ₯Ό μˆ˜μ • κ°€λŠ₯
  • 단, μž¬ν• λ‹Ή(μ£Όμ†Œ λ³€κ²½)은 μ›λž˜ 객체에 영ν–₯을 μ£Όμ§€ μ•ŠμŒ

Reference​