1. 程式人生 > >js深拷貝初識

js深拷貝初識

淺拷貝和深拷貝的區別
   淺拷貝:只拷貝物件的基礎屬性值,對屬性值為物件或陣列的屬性則拷貝指標。 
   深拷貝:拷貝物件的所有屬性作為一個全新的物件。拷貝前後的物件互不影響。

淺拷貝

var a = {name:"test",children:{name:"test1"}}
//淺拷貝
var b = {
    name:a.name,
    children:a.children
}
a.name = "字面量屬性拷貝"
a.children.name = "淺拷貝"
console.log(a)//Object {name: "字面量屬性拷貝", children: Object{name:"淺拷貝"}}
console.log(b)//Object {name: "test", children: Object{name:"淺拷貝"}}
 


可以看出淺拷貝只拷貝了物件的基礎屬性值,對物件或陣列的屬性值則是隻是拷貝了引用。所以修改a.name的時候,由於name的屬性值為字串所以直接拷貝了,a的修改不影響b。當修改a.children屬性的時候,由於該屬性值是個物件,所以b只拷貝了引用,故b.children也變化了

深拷貝
 

var a = {name:"test",children:{name:"test1"}}
//深拷貝
var b = {
    name:a.name,
    children:{name:a.children.name}
}
a.name = "字面量屬性拷貝"
a.children.name = "淺拷貝"
console.log(a)//Object {name: "字面量屬性拷貝", children: Object{name:"淺拷貝"}}
console.log(b)//Object {name: "test", children: Object{name:"test1"}}

  
深拷貝是對淺拷貝的進一步解析,直到所有的屬性都為基礎屬性值為止,所以深拷貝的物件是完全獨立的一個新物件。

深拷貝公共方法封裝

/* ================ 深拷貝 ================ */
//返回傳遞給他的任意物件的類
const isClass = (o) => {
  if (o === null) return "Null";
  if (o === undefined) return "Undefined";
  return Object.prototype.toString.call(o).slice(8, -1);
}

//深度克隆
const deepClone = (obj) => {
  if (!obj) { return null }
  let result, oClass = isClass(obj);
  //確定result的型別
  if (oClass === "Object") {
    result = {};
  } else if (oClass === "Array") {
    result = [];
  } else {
    return obj;
  }

  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      let copy = obj[key];
      if (isClass(copy) == "Object") {
        result[key] = deepClone(copy);//遞迴呼叫
      } else if (isClass(copy) == "Array") {
        result[key] = deepClone(copy);
      } else {
        result[key] = obj[key];
      }
    }
  }
  return result;
}

 

Object.assign()
特別注意:ES6提供了一個Object.assign()方法用於拷貝和合並物件,但是該方法也只是一個淺拷貝方法,使用時請慎重。