Skip to content

Latest commit

 

History

History
152 lines (110 loc) · 5.7 KB

File metadata and controls

152 lines (110 loc) · 5.7 KB

1. 원시 값(Primitive)

  • string, number, boolean, null, undefined, symbol, BigInt
  • 값 자체를 저장하며, 변경 불가능(Immutable)
  • === 비교 시 값만 비교 (10 === 10 → true)
  • 메모리: 스택(Stack)에 저장

** 2. 객체(Object)**

  • {}, [], function() {}, new Date(), new Map()
  • 참조 타입, 변경 가능(Mutable)
  • === 비교 시 메모리 주소(참조) 비교 ({ a: 1 } !== { a: 1 })
  • 메모리: 힙(Heap)에 저장, 변수는 참조(Reference) 저장
구분 원시 값 (Primitive) 객체 (Object)
저장 방식 값 자체를 저장 참조(Reference) 저장
메모리 위치 스택(Stack) 힙(Heap)
비교 방식 값 자체 비교 (===) 참조(메모리 주소) 비교 (===)
변경 가능 여부 불변(Immutable) 변경 가능(Mutable)
예제 let a = 10; let obj = { name: "Alice" };
  • 원시값은 변수에 할당 시, 변수(확보된 메모리 공간)에는 실제 값이 저장됨.
  • 객체를 변수에 할당 시, 변수(확보된 메모리 공간)에는 참조 값이 저장됨.

변경 가능성(Mutable)

  • 객체를 변수에 저장하면, 해당 변수에는 **객체의 값이 아닌 참조(메모리 주소)**가 저장됨.
  • 객체는 같은 메모리 주소를 공유하므로, 하나를 변경하면 다른 변수도 영향을 받음.
let obj1 = { name: "Alice" };
let obj2 = obj1; // 같은 객체를 참조

obj2.name = "Bob"; // obj2에서 변경하면 obj1도 영향을 받음

console.log(obj1.name); // "Bob"
console.log(obj2.name); // "Bob"

참조에 의한 전달(Call by Reference)

  • 함수에 객체를 전달하면, 객체의 참조(메모리 주소)가 전달되므로 함수 내부에서 변경하면 원본 객체도 변경됨.
  • 객체가 함수의 매개변수로 전달되면, 새로운 복사본이 아니라 같은 객체를 참조함.
function update(obj) {
  obj.name = "Charlie";
}

let user = { name: "Alice" };
update(user);

console.log(user.name); // "Charlie" (원본 객체가 변경됨)

깊은 복사(Deep Copy) vs. 얕은 복사(Shallow Copy)

1. 얕은 복사(Shallow Copy)

객체의 1단계 속성(직접 포함된 속성)만 복사하고, 중첩된 객체(하위 객체)는 참조만 복사하는 방식

방법

  1. Object.assign()
const obj1 = { name: "Alice", address: { city: "Seoul" } };
const obj2 = Object.assign({}, obj1);

obj2.name = "Bob"; // 기본 속성은 복사됨 (독립적)
obj2.address.city = "Busan"; // 중첩 객체는 참조 복사됨

console.log(obj1.name); // "Alice" (영향 없음)
console.log(obj2.name); // "Bob"
console.log(obj1.address.city); // "Busan" (중첩 객체가 변경됨!)
  1. 스프레드 연산자 { ...obj }
const obj1 = { name: "Alice", address: { city: "Seoul" } };
const obj2 = { ...obj1 };

obj2.name = "Bob"; // 기본 속성은 복사됨 (독립적)
obj2.address.city = "Busan"; // 중첩 객체는 참조 복사됨

console.log(obj1.address.city); // "Busan" (중첩 객체가 변경됨)

📌 얕은 복사의 문제점 • 1단계 속성(Primitive Value)은 복사됨 → 독립적으로 변경 가능. • 중첩 객체(하위 객체)는 참조만 복사됨 → 변경 시 원본도 영향을 받음. • 즉, 중첩된 객체를 변경하면 원본도 변경되는 문제 발생!

2. 깊은 복사(Deep Copy)

객체 내부의 모든 값(중첩 객체 포함)을 새로운 메모리에 복사하여 독립적인 객체 만드는 방식

방법 1. JSON 방식 (JSON.parse(JSON.stringify(obj))) ✅ 모든 객체가 새로 복사됨 → 원본 객체에 영향을 주지 않음. ❌ 단점: JSON.stringify()는 함수, undefined, Symbol 같은 값은 제거됨!

const obj1 = { name: "Alice", address: { city: "Seoul" } };
const obj2 = JSON.parse(JSON.stringify(obj1));

obj2.name = "Bob"; // 기본 속성은 복사됨
obj2.address.city = "Busan"; // 중첩 객체도 독립적으로 변경 가능

console.log(obj1.address.city); // "Seoul" (원본 유지됨!)
console.log(obj2.address.city); // "Busan"

2. lodash 라이브러리 (_.cloneDeep(obj)) ✅ lodash의 _.cloneDeep()을 사용하면 함수, undefined도 포함한 완전한 깊은 복사가 가능!

const _ = require("lodash");

const obj1 = { name: "Alice", address: { city: "Seoul" } };
const obj2 = _.cloneDeep(obj1);

obj2.address.city = "Busan";

console.log(obj1.address.city); // "Seoul" (원본 유지됨)
console.log(obj2.address.city); // "Busan"

3. 구조적 복사 (structuredClone(obj), 최신 브라우저 지원) ✅ 최신 브라우저에서 네이티브 깊은 복사 지원! ❌ 함수(function)는 복사되지 않음!

const obj1 = {
  name: "Alice",
  address: { city: "Seoul" },
  greet: () => "Hello",
};
const obj2 = structuredClone(obj1);

obj2.address.city = "Busan";

console.log(obj1.address.city); // "Seoul" (원본 유지됨)
console.log(obj2.address.city); // "Busan"
복사 방식 기본 속성 복사 중첩 객체 복사 원본 영향 여부 사용 방법
얕은 복사 ✅ 독립적 복사 ❌ 참조만 복사 🛑 원본 영향 받음 Object.assign(), { ...obj }
깊은 복사 ✅ 독립적 복사 ✅ 완전한 복사 ✅ 원본 영향 없음 JSON.parse(JSON.stringify(obj)), _.cloneDeep(), structuredClone()