簡簡單單在 JavaScript 中克隆對象

做者:Angelos Chalaris

瘋狂的技術宅javascript

原文:https://www.30secondsofcode.o...前端

未經容許嚴禁轉載java

JavaScript 的原始數據類型(例如number、string、null,undefined 和 boolean)是不可變的,這意味着一旦建立,它們的值就沒法更改。可是對象和數組是可變的,容許在建立後修改其值。實際上,這意味着基元是經過值傳遞的,而對象和數組是經過引用傳遞的。考慮如下例子:程序員

let str = 'Hello';
let copy = str;
copy = 'Hi';
// str = 'Hello', copy = 'Hi'

let obj = { a: 1, b: 2 };
let objCopy = obj;
objCopy.b = 4;
// obj = { a: 1, b: 4}, objCopy = { a: 1, b: 4 }

obj 中發生的事是該對象是經過引用傳遞給 objCopy 的,所以修改其中一個變量的值也會影響另外一個變量。 objCopy 其實是引用同一對象的別名。咱們能夠使用多種技術(例如,展開運算符(...)或帶有空對象的 Object.assign())來克隆對象,以解決此問題:面試

let obj = { a: 1, b: 2};
let clone = { ...obj };
clone.b = 4;
// obj = { a: 1, b: 2}, clone = { a: 1, b: 4 }

let otherClone = Object.assign({}, obj);
otherClone.b = 6;
clone.b = 4;
// obj = { a: 1, b: 2}, otherClone = { a: 1, b: 6 }

這兩種解決方案都展現了淺克隆的例子,由於它們適用於外部(淺)對象,可是若是咱們嵌套(深)對象,這些對象最終將經過引用傳遞,從而致使失敗。有幾種方法能夠解決這個問題,其中更簡單的方法是用 JSON.stringify()JSON.parse() 處理:segmentfault

let obj = { a: 1, b: { c: 2 } };
let clone = JSON.parseJSON.stringify(obj));
clone.b.c = 4;
// obj = { a: 1, b: { c: 2 }}, clone = { a: 1, b: { c: 4 } }

雖然上面的例子有效,但它必須序列化和反序列化整個對象,這可能會嚴重影響代碼的性能,因此它可能不適用於較大的對象或對性能要求很高的項目。數組

另外,你能夠用遞歸來深度克隆對象,而且速度要快得多,例以下面代碼中的遞歸函數。一樣,若是你想使用現成的淺克隆函數,則能夠這樣作:const shallowClone = obj => Object.assign({}, obj);服務器

const deepClone = obj => {
  if (obj === null) return null;
  let clone = Object.assign({}, obj);
  Object.keys(clone).forEach(
    key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key])
  );
  return Array.isArray(obj) && obj.length
    ? (clone.length = obj.length) && Array.from(clone)
    : Array.isArray(obj)
      ? Array.from(obj)
      : clone;
};

本文首發微信公衆號:前端先鋒

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章

歡迎繼續閱讀本專欄其它高贊文章:


相關文章
相關標籤/搜索