Dev/JavaScript

[JavaScript] 객체와 배열을 복사하는 방법들

BiCute 2023. 2. 2. 08:00
반응형

 

 

# JSON.parse(JSON.stringify(obj))

let originalArray = [1, 2, 3, 4, 5];
let copiedArray = JSON.parse(JSON.stringify(originalArray));
console.log(copiedArray); // [1, 2, 3, 4, 5]

JSON.stringify(obj)는 JavaScript 개체를 JSON 문자열로 변환하는 JavaScript의 메서드입니다. JSON.parse(jsonString)는 JSON 문자열을 JavaScript 객체로 변환하는 메서드입니다.

객체는 JSON.stringify(obj)를 통해 JSON 문자열로 변환된 다음 해당 문자열을 JSON.parse(jsonString)를 사용하여 다시 객체로 변환합니다.

이러한 방식으로 생성된 새로운 객체는 원래 객체와 별도로 독립된 복사본이 됩니다.

 

 

 

# spread operator

let originalArray = [1, 2, 3, 4, 5];
let copiedArray = [...originalArray];
console.log(copiedArray); // [1, 2, 3, 4, 5]

스프레드 연산자는 직렬화 또는 구문 분석 작업을 포함하지 않기 때문에 성능 측면에서 JSON.parse(JSON.stringify(obj))보다 훨씬 더 효율적입니다.

 

하지만 이 방법은 열거 가능한 속성으로만 작업하고 중첩된 객체에 대한 전체 복사를 수행할 수 없는 등의 고유한 제한 사항이 있습니다.

 

※ 직렬화: 직렬화는 개체의 상태를 저장(예: 파일 또는 데이터베이스)하거나 전송(예: 네트워크 연결을 통해)하고 나중에 재구성할 수 있는 형식으로 변환하는 프로세스입니다. 개체를 직렬화하는 가장 일반적인 방법은 JSON.stringify(obj)를 사용하여 개체를 JSON 문자열로 변환하는 것 입니다.

 

※ 구문 분석: 구문 분석은 직렬화된 형식을 다시 개체로 변환하는 프로세스입니다. JSON 문자열을 구문 분석하는 가장 일반적인 방법은 JSON.parse(jsonString)을 사용하는 것입니다.

 

 

Nested Object

중첩된 객체(nested object)는 다른 객체나 배열 안에 있는 객체입니다.

예를들면, 아래 객체에는 address라는 중첩된 객체가 있습니다.

let person = {
  name: "zenn",
  age: 30,
  address: {
    street: "56-1",
    city: "akihabara",
    state: "japan"
  }
};

 

스프레드 연산자를 사용하면 원래 객체의 모든 속성과 값을 포함하는 새 개체가 생성되지만 중첩된 객체인 address는 여전히 원래 객체에 대한 참조를 갖고 있습니다.

예를들면 다음과 같습니다.

let person2 = {...person};
console.log(person2.address === person.address); // true
person2.address.city = "seoul";
console.log(person.address.city); // "seoul"

 

중첩된 개체의 전체 복사본을 원하는 경우 lodash.cloneDeep과 같은 일부 라이브러리를 사용하거나 개체의 모든 속성을 재귀적으로 복사하는 고유한 함수를 작성하여 중첩된 개체에 대한 새 개체를 만들 수 있습니다.

 

 

Recursive Copy Function

재귀적으로 복사하는 함수의 예

function deepCopy(obj) {
  let copy;

  // 3가지 단순 유형 및 null 또는 undefined 처리
  if (null == obj || "object" != typeof obj) return obj;

  // Date
  if (obj instanceof Date) {
      copy = new Date();
      copy.setTime(obj.getTime());
      return copy;
  }

  // BigInt
  if (typeof obj === 'bigint') {
    return BigInt(obj.toString())
  }

  // Symbol
  if (typeof obj === 'symbol') {
    return Symbol(obj.toString())
  }

  // Array
  if (obj instanceof Array) {
      copy = [];
      for (let i = 0, len = obj.length; i < len; i++) {
          copy[i] = deepCopy(obj[i]);
      }
      return copy;
  }

  // Object
  if (obj instanceof Object) {
      copy = {};
      for (let attr in obj) {
          if (obj.hasOwnProperty(attr)) copy[attr] = deepCopy(obj[attr]);
      }
      return copy;
  }

  throw new Error("지원되지 않는 유형입니다.");
}

 

TEST CODE

let original = {
  symbol: Symbol("test"),
  bigint: BigInt(1234567890)
};
let copy = deepCopy(original);
console.log(copy.symbol === original.symbol); //false
console.log(copy.bigint === original.bigint); //false

 

 

 

 

Other Available Methods for Copying

Object.assign()

let originalObject = { a: 1, b: 2, c: 3 };
let copiedObject = Object.assign({}, originalObject);
console.log(copiedObject); // { a: 1, b: 2, c: 3 }

Object.assign()은 첫번째 인자로 타겟을 지정하고, 두번째 인자로 소스가 되는 오브젝트를 선택합니다.

선택된 오브젝트들은 타겟 오브젝트에 병합이 됩니다.

Object.assign()는 열거 가능한 속성만 복사하므로 열거 불가능한 속성은 복사되지 않습니다.
원본 개체에 직접 있는 속성만 복사합니다. 

스프레드 오퍼레이터와 같이 중첩된 개체 및 배열은 값이 아닌 참조로 복사됩니다. 

즉, 새 개체에서 중첩된 개체 또는 배열을 수정하면 원래 개체에서도 수정됩니다.

 

 

Array.from()

let original = [1,2,3,4];
let copy = Array.from(original);
console.log(copy); // [1,2,3,4]
console.log(original===copy); // false

배열의 경우 스프레드 연산자( ...) 또는 Array.from()메서드를 사용하여 배열의 전체 복사본을 만들 수 있습니다.

 

 

 

반응형