[TIL] JS - 객체를 복사하는 방법

15163 단어 TILTIL

오늘은 Mocha & Chai 테스트 케이스를 작성하면서 지금까지 3주동안 배운 자바스크립트 기본 개념들을 복습하는 시간을 가졌다. 대부분 이미 아는 내용들이었지만 새롭게 알게 된 것들도 있어서 정리해 보았다. 지금까지 객체를 얕은 복사할 때 항상 스프레드 연산자만 사용했었는데 Object.assign() 메서드는 이번에 처음 사용해 보았다. 주말에는 Mocha & Chai로 유닛 테스트 하는 법에 대해 조금 더 공부해 보아야겠다.

페어 프로그래밍이 조금 일찍 끝나서 JS 연습할 겸 시작한 개인 프로젝트 Vanilla Gallery를 진행하였다. 어제 레이아웃과 Modal까지 구현했고, 오늘은 각 그림들의 정보를 담은 JSON을 작성해서 XMLHttpRequest로 script.js에 불러왔다. 불러온 JSON을 parse해서 data를 읽어와지긴 하는데 그거랑 별개로 Uncaught SyntaxError: Unexpected token ':'라고 에러가 자꾸 뜬다. JSON Validator로 검사했을 때 이상이 없으니 JSON 파일 자체 문제는 아닌 것 같은데 구글링해도 명확한 답을 찾기가 어렵다. 내일 일과 후에 좀 더 찾아봐야 할 것 같다.


Today I Learned

// 복사할 객체 person1
const person1 = {
  name: 'Alex',
  birthYear: 1993,
  languages: ['Korean', 'English', 'Spanish'],
  grade: {
    korean: 'A',
    english: 'B',
    spanish: 'B',
  },
  getAge() {
    const currentYear = new Date().getFullYear();
    return currentYear - this.birthYear;
  },
};

1. 참조 복사 (Reference Copy)

  • value가 아닌 reference를 복사
  • 원본과 복사본 모두 같은 메모리 주소를 향한 reference를 가지고 있음
const person2 = person1;

console.log(person1 === person2);// true

person2.name = 'Lewis';
console.log(person1.name); // 'Lewis'
console.log(person2.name); // 'Lewis'

2. 얕은 복사 (Shallow Copy)

  • Depth 1까지는 복사가 이루어지나 Depth 2부터는 이루어지지 않음
  • 객체 안의 객체, 배열, 함수는 reference만 복사됨
  • 복사 방법
    • Object.assign( {}, originalObj )
    • { ...originalObj }
// Object.assign()
const person3 = Object.assign({}, person1);

console.log(person1 === person3); // false
console.log(person1.languages === person3.languages); // true
console.log(person1.grade === person3.grade); // true
console.log(person1.getAge === person3.getAge); // true 

person3.name = 'Lewis';
console.log(person1.name); // 'Alex'
console.log(person3.name); // 'Lewis'

person3.languages[0] = 'German';
console.log(person1.languages[0]); // 'German'
console.log(person3.languages[0]); // 'German'

3. 깊은 복사 (Deep Copy)

  • 모든 Depth에서 복사가 이루어짐
  • 복사 방법
    • JSON.parse(JSON.stringify(originalObj)) : 불완전
    • 라이브러리 사용 : Lodash, Ramda
// JSON.parse & JSON.stringify
	// JS 객체를 JSON 스트링으로 변환하였다가 다시 JS 객체로 변환
	// 객체가 아예 새롭게 생성되기 때문에 depth와 상관 없이 reference 복사는 일어나지 않음
	// 변환 불가능한 타입이 존재 (함수, BigInt)
const person4 = JSON.parse(JSON.stringify(person1));

console.log(person1 === person4); // false
console.log(person1.languages === person4.languages); // false
console.log(person1.grade === person4.grade); // false
console.log(person1.getAge === person4.getAge); // false
console.log('getAge' in person4); // false

person4.name = 'Lewis';
console.log(person1.name); // 'Alex'
console.log(person4.name); // 'Lewis'

person3.languages[0] = 'German';
console.log(person1.languages[0]); // 'Korean'
console.log(person4.languages[0]); // 'German'

console.log(person1.getAge()); // 28
console.log(person4.getAge()); // Error

좋은 웹페이지 즐겨찾기