Articles Categories Tags About
【JS】Object Deep Copy 推薦用法比較
Programming · 3 min read

【JS】Object Deep Copy 推薦用法比較

Object 因為 Call by sharing 的特性,無法直接用 `=` 複製 Object,今天來講解 Object 的幾種複製方式。 ## 懶人包 - 正常Object(單層): `...` - Nested Object(多層):Lodash `cloneDeep`

Object 因為 Call by sharing 的特性,無法直接用 = 複製 Object,今天來講解 Object 的幾種複製方式。

懶人包

  • 正常Object(單層): ...
  • Nested Object(多層):Lodash cloneDeep

何謂shallow copy(淺複製)

因Javascript特性對於Object會是call by reference,直接用 = 會是shallow copy

a = { b: 1, c: 2 };
copy = a;
copy.b = 100;

// shallow copy
console.log(a.b); // 100

copy用法差異

MethodProsCons
=直接明瞭,預設用法shallow copy(淺複製)
JSON.stringify() and JSON.parse()deep copy nested objects(多層Object)不能複製物件型別(Function, Date)
Object.assign()deep copy 第一層不能deep copy nested objects
… spread operator同上,語法簡單,複製單層object首選不能deep copy nested objects
Lodash cloneDeep複製nested objects包含functions外部package依賴
structuredClone()deep copy nested objects(多層Object)僅支持可結構化的變數,遇到 Error 和 Function 會拋出 DOMException

=

let john = { name: 'John', age: 28 };
let ken = john;
ken.name = 'ken';

// ❌ Bad: can't deep copy
console.log(john.name); // ken

JSON.stringify() and JSON.parse()

let john = {
  name: 'John',
  age: 28,
  job: () => 'Web Developer',
  address: {
    city: 'taipei',
  },
};
let ken = JSON.parse(JSON.stringify(john));
ken.name = 'ken';
ken.address.city = 'new taipei';

// ✅ Good: deep copy
console.log(john.name); // john
console.log(john.address.city); // taipei

// ❌ Bad: function missing
console.log(ken.job); // undefined

Object.assign()

let john = {
  name: 'John',
  age: 28,
  job: () => 'Web Developer',
  address: {
    city: 'taipei',
  },
};
let ken = Object.assign({}, john);
ken.name = 'ken';
ken.address.city = 'new taipei';

// ✅ Good
console.log(john.name); // john
console.log(ken.job()); // Web Developer

// ❌ Bad: can't deep copy nested objects
console.log(john.address.city); // new taipei

... spread operator

let john = {
  name: 'John',
  age: 28,
  job: () => 'Web Developer',
  address: {
    city: 'taipei',
  },
};
let ken = { ...john };
ken.name = 'ken';
ken.address.city = 'new taipei';

// ✅ Good: deep copy
console.log(john.name); // john
console.log(ken.job()); // WebDeveloper

// ❌ Bad: not deep copy nested object
console.log(john.address.city); // new taipei

Lodash cloneDeep

let john = {
  name: 'John',
  age: 28,
  job: () => 'Web Developer',
  address: {
    city: 'taipei',
  },
};
let ken = _.cloneDeep(john);
ken.name = 'ken';
ken.address.city = 'new taipei';

// ✅ Good: deep copy
console.log(john.name); // john
console.log(john.address.city); // taipei
console.log(ken.job()); // WebDeveloper

structuredClone()

let john = {
  name: 'John',
  age: 28,
  birthday: new Date('2022-08-08'),
  address: {
    city: 'taipei',
  },
};
let ken = structuredClone(john);
ken.name = 'ken';
ken.address.city = 'new taipei';
ken.birthday.setDate('30');

// ✅ Good: deep copy
console.log(john.name); // john
console.log(john.address.city); // taipei
console.log(john.birthday.toDateString()); // Mon Aug 08 2022
console.log(ken.name); // ken
console.log(ken.address.city); // new taipei
console.log(ken.birthday.toDateString()); // Tue Aug 30 2022

// ❌ Bad: not support Function
let amy = {
  job: () => 'designer',
};
structuredClone(amy); // Throw DOMException

參考



Logan

Senior software engineer, passionate about coding and smart home 🏠

Licensed under CC BY-NC 4.0


Share:


Related Articles


Type to search articles