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()方法用于拷贝和合并对象,但是该方法也只是一个浅拷贝方法,使用时请慎重。

猜你喜欢

转载自blog.csdn.net/mafan121/article/details/74420957