美文网首页
对象拷贝

对象拷贝

作者: 行走的蛋白质 | 来源:发表于2021-04-09 10:06 被阅读0次

一. 深拷贝 / 浅拷贝

1. 浅拷贝: 指针拷贝, 让拷贝前和拷贝后对象的指针指向同一块内存地址
  • 增加了原对象的引用计数
  • 没有新的内存分配
let obj1 = {
    a: 1,
    b: 2
}
let obj2 = obj1
obj1.a = 3
console.log(obj2.a) // 3
2. 深拷贝
  • Object.assign(),只能拷贝一层, 且会改变原有对象 - ( 数组 concat 方法不会改变原有数组 )
  • ES6 扩展运算符 { ...obj },同样只能拷贝一层
  • immutable.js 实现,利用其不可变数据集的特性,省去深拷贝环节每次改变只影响当前节点和它的父节点, 其他节点复用,效率高
  • lodash 库的 cloneDeep 方法实现深拷贝
  • 遍历 for in / Object.keys(obj) 递归, 代码以及优缺点如下:
1). JSON.parse(JSON.stringify()) 实现深拷贝的不足
    1. 如果 obj 里面有时间对象,则 JSON.stringify 后再 JSON.parse 的结果,时间将只是字符串的形式。而不是时间对象;
const obj = {
  date: new Date()
}
const newObj = JSON.parse(JSON.stringify(obj))
console.log(Object.prototype.toString.call(obj.date)) // [object Date]
console.log(Object.prototype.toString.call(newObj.date)) // [object String]
console.log(newObj.date) // 2021-04-09T02:12:31.440Z
    1. 如果 obj 里有 RegExp、Error 对象,则序列化的结果将只得到空对象;
const obj = {
  date: new Date(),
  regExp: new RegExp('\d'),
  error: new Error('error')
}
const newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj.regExp) // {}
console.log(newObj.error) // {}
    1. 如果 obj 键名有 Symbol 或者值里有函数,undefined,则序列化的结果会丢失;
const obj = {
  date: new Date(),
  regExp: new RegExp('\d'),
  error: new Error('error'),
  fn: function() {
    console.log('function')
  },
  und: undefined
}
const sym = Symbol('sym')
test[sym] = 'sym'
const newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj) // {date: "2021-04-10T01:47:04.806Z", regExp: {…}, error: {…}}
    1. 如果 obj 里有 NaN、Infinity 和 -Infinity,则序列化的结果会变成 null
const obj = {
  date: new Date(),
  regExp: new RegExp('\d'),
  error: new Error('error'),
  fn: function() {
    console.log('function')
  },
  und: undefined,
  nan: NaN,
  infi: Infinity
}
const newObj = JSON.parse(JSON.stringify(obj))
console.log(Object.prototype.toString.call(obj.date))
console.log(Object.prototype.toString.call(newObj.date))
console.log(newObj.nan) // null
console.log(newObj.infi) // null
    1. JSON.stringify() 只能序列化对象的可枚举的自有属性,例如 如果 obj 中的对象是有构造函数生成的, 则使用 JSON.parse(JSON.stringify(obj)) 深拷贝后,会丢弃对象的 constructor;
function Person(name) {
  this.name = name
}
const zs = new Person('zhangsan')
const obj = {
  date: new Date(),
  regExp: new RegExp('\d'),
  error: new Error('error'),
  fn: function() {
    console.log('function')
  },
  und: undefined,
  nan: NaN,
  infi: Infinity,
  zs
}
const newObj = JSON.parse(JSON.stringify(obj))
console.log(obj.zs)
console.log(newObj.zs)
compare
    1. 如果对象中存在循环引用的情况也无法正确实现深拷贝;
对象循环引用
2). Reflect 递归实现
function deepClone(obj) {
    // 判断如果 obj 是基本类型数据或者函数, 直接返回
    if (!obj || typeof obj !== 'object') return obj;
    if (obj instanceof Error) {
        return new Error(obj);
    }
    if (obj instanceof RegExp) {
        return new RegExp(obj);
    }
    if (obj instanceof Date) {
        return new Date(obj);
    }
    const result = Array.isArray(obj) ? [] : {};
    Reflect.ownKeys(obj).forEach(item => {
        if (obj[item] && typeof obj[item] === 'object') {
            result[item] = deepClone(obj[item]);
        } else {
            result[item] = obj[item];
        }
    })
    return result;
}
// 测试
const a = '111'
console.log(deepClone(a))
const test = {
    num: 0,
    str: '',
    boolean: true,
    unf: undefined,
    nul: null,
    obj: {
        name: '我是一个对象',
        num: 1,
        id: 1
    },
    arr: [0, 1, 2],
    func: function() {
        console.log('我是一个函数')
    },
    date: new Date(0),
    reg: new RegExp('我是一个正则', 'ig'),
    err: new Error('error')
}
const sym = Symbol('我是一个Symbol')
test[sym] = 'Symbol'
console.log(deepClone(test))
console.log(deepClone(test.date))
console.log(deepClone(test.reg))
console.log(deepClone(test.err))
Reflect_deepClone_result
  • 递归方法深拷贝互相引用的对象会造成栈溢出

相关文章

  • java 对象的拷贝

    拷贝:即复制 对象拷贝:即对象复制 java 对象拷贝分类:浅拷贝、深拷贝 java 对象的浅拷贝和深拷贝针对包含...

  • Java-序列化—(三)序列化实现深拷贝

    浅拷贝是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象。深拷贝不仅拷贝对象...

  • Objective-C中的深拷贝与浅拷贝

    一、概念 浅拷贝——只拷贝指向对象的指针,不拷贝引用对象本身。 深拷贝——拷贝引用对象本身。将对象obj,拷贝后得...

  • iOS - copy与mutableCopy

    浅拷贝与深拷贝 浅拷贝:指针拷贝,不产生新的对象,源对象的引用计数器+1 深拷贝:对象拷贝,会产生新的对象,源对象...

  • 深拷贝和浅拷贝不同

    浅拷贝:指针(地址)拷贝,不会产生新对象深拷贝:内容拷贝,会产生新对象 非容器类对象的深拷贝、浅拷贝 非容器类对象...

  • 前端笔记(二) 对象的深浅拷贝,函数的防抖与节流,函数柯里化 ,

    对象的深浅拷贝 对象的深拷贝与浅拷贝的区别: 浅拷贝:仅仅复制对象的引用, 而不是对象本身。 深拷贝:把复制的对象...

  • 引用赋值和浅拷贝和深拷贝

    1.对象的引用赋值 2.对象的浅拷贝 浅拷贝:是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象...

  • 深浅copy

    概念:浅拷贝:不拷贝对象,只拷贝对象指针,因此不会产生新的对象。深拷贝:拷贝对象到新的内存,因此会产生新的对象。 ...

  • 2018-10-10函数基础

    深拷贝和浅拷贝 深拷贝 copy.deepcopy(对象)浅拷贝 copy.copy(对象)深拷贝: 将对象对应的...

  • Cloneable 接口

    浅拷贝(shallow clone)和深拷贝(deep clone) 浅拷贝是指拷贝对象时仅仅拷贝对象本身和对象中...

网友评论

      本文标题:对象拷贝

      本文链接:https://www.haomeiwen.com/subject/kahikltx.html