浅拷贝和深拷贝

深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的。

一、概念描述。

1.浅拷贝: 拷贝的对象的属性分为基本类型值和引用类型的值

        ①基本类型:拷贝的就是基本类型的值

        ②引用类型:拷贝的就是内存地址新旧对象共享同一块内存,如果改了新对象的值也是会影响旧对象的值的

2.深拷贝: 深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象(新旧对象不共享同一块内存,相互不影响

二、赋值和浅拷贝的区别。

        赋值:一个对象赋值给一个新变量的时候,赋值的是对象在栈中的地址,而不是堆中的数据,两个对象是相互影响联动的。

        浅拷贝:按位拷贝对象,它会创建一个新的对象,这个对象有着原始对象属性值的一份精确拷贝。但只是复制对象空间而不复制资源。

三、堆内存和栈内存。

四、赋值和浅拷贝举例。

1.赋值。

// 对象赋值
let obj1 = {
    name: 'Chen',
    age: 18,
    hobby: ['see a film', 'write the code', 'play basketball', 'tourism']
}

let obj2 = obj1;
obj2.name = 'Forever';
obj2.hobby[1] = 'swim';
obj2.hobby[2] = 'alpinism';
console.log('obj1===>', obj1);
console.log('obj2===>', obj2);

2.浅拷贝。

// 浅拷贝
let obj1 = {
    name: 'Chen',
    age: 18,
    hobby: ['see a film', 'write the code', 'play basketball', 'tourism']
}

let obj3 = {...obj1};
obj3.name = 'Forever';
obj3.hobby[1] = 'swim';
obj3.hobby[2] = 'alpinism';
console.log('obj1===>', obj1);
console.log('obj3===>', obj3);

五、浅拷贝的实现。

1.展开运算符(...) 

// 展开运算符... 实现浅拷贝
let obj1 = {
    name: 'Chen',
    hobby: ['see a film', 'write the code', 'play basketball', 'tourism']
}

let obj2 = {...obj1};
obj2.hobby[1] = 'swim';
obj2.hobby[2] = 'alpinism';
obj2.name = 'Forever';
console.log('obj1===>', obj1); // obj1===> { name: 'Chen',hobby: [ 'see a film', 'swim','alpinism', 'tourism']}
console.log('obj2===>', obj2); // obj2===> { name: 'Forever',hobby: [ 'see a film', 'swim','alpinism', 'tourism']}

2.Object.assign()

// Object.assign() 实现浅拷贝
let obj1 = {
  name: "Chen",
  hobby: ["see a film", "write the code", "play basketball", "tourism"],
};

let obj2 = Object.assign({}, obj1);
obj2.hobby[1] = "swim";
obj2.hobby[2] = "alpinism";
obj2.name = "Forever";
console.log("obj1===>", obj1); // obj1===> {name: 'Chen',hobby: [ 'see a film', 'swim', 'alpinism', 'tourism' ]}
console.log("obj2===>", obj2); // obj2===> {name: 'Forever',hobby: [ 'see a film', 'swim', 'alpinism', 'tourism' ]}

 

 3. Array.prototype.concat()

// Array.prototype.concat() 实现浅拷贝
let arr1 =  [
    {
        name: 'Chen'
    },
    'see a film', 
    'write the code', 
    'play basketball', 
    'tourism'
];
let arr2 = arr1.concat([]);
arr2[0].name = 'Forever';
arr2[1] = 'play games';
console.log('arr1===>', arr1); // arr1===> [{ name: 'Forever' },'see a film','write the code','play basketball', 'tourism']
console.log('arr2===>', arr2); // arr2===> [{ name: 'Forever' },'play games','write the code', 'play basketball', 'tourism']

4.  Array.prototype.slice()

// Array.prototype.concat() 实现浅拷贝
let arr1 =  [
    {
        name: 'Chen'
    },
    'see a film', 
    'write the code', 
    'play basketball', 
    'tourism'
];
let arr2 = arr1.slice();
arr2[0].name = 'Forever';
arr2[1] = 'play games';
console.log('arr1===>', arr1); // arr1===> [{ name: 'Forever' },'see a film','write the code','play basketball', 'tourism']
console.log('arr2===>', arr2); // arr2===> [{ name: 'Forever' },'play games','write the code', 'play basketball', 'tourism']

 六、深拷贝实现。

  1.JSON.parse(JSON.stringify())

//  JSON.parse(JSON.stringify())实现深拷贝Object
let obj1 = {
    name: 'Chen',
    hobby: ['see a film', 'write the code', 'play basketball', 'tourism']
}
let obj2 = JSON.parse(JSON.stringify(obj1));
console.log(obj1 === obj2); // false
obj2.name = 'Forever';
obj2.hobby[1] = 'swim';
obj2.hobby[2] = 'alpinism';

console.log('obj1===>', obj1); 
// obj1===> { name: 'Chen',hobby: ['see a film', 'write the code', 'play basketball', 'tourism']}
console.log('obj2===>', obj2); 
// obj2===> { name: 'Forever',hobby: ['see a film', 'swim', 'alpinism', 'tourism']}

 2.JSON.stringify()的缺点:

  • undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时)。函数、undefined 被单独转换时,会返回 undefined,如JSON.stringify(function(){}) or JSON.stringify(undefined).
  • 对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误。
  • 所有以 symbol 为属性键的属性都会被完全忽略掉,即便 replacer 参数中强制指定包含了它们。
  • Date 日期调用了 toJSON() 将其转换为了 string 字符串(同 Date.toISOString()),因此会被当做字符串处理。
  • NaN 和 Infinity 格式的数值及 null 都会被当做 null。
  • 其他类型的对象,包括 Map/Set/WeakMap/WeakSet,仅会序列化可枚举的属性。
JSON.stringify({}); // '{}'
JSON.stringify(true); // 'true'
JSON.stringify("foo"); // '"foo"'
JSON.stringify([1, "false", false]); // '[1,"false",false]'
JSON.stringify({ x: 5 }); // '{"x":5}'

JSON.stringify({ x: 5, y: 6 });
// "{"x":5,"y":6}"

JSON.stringify([new Number(1), new String("false"), new Boolean(false)]);
// '[1,"false",false]'

JSON.stringify({ x: undefined, y: Object, z: Symbol("") });
// '{}'

JSON.stringify([undefined, Object, Symbol("")]);
// '[null,null,null]'

JSON.stringify({ [Symbol("foo")]: "foo" });
// '{}'

JSON.stringify({ [Symbol.for("foo")]: "foo" }, [Symbol.for("foo")]);
// '{}'

JSON.stringify({ [Symbol.for("foo")]: "foo" }, function (k, v) {
  if (typeof k === "symbol") {
    return "a symbol";
  }
});

// undefined

// 不可枚举的属性默认会被忽略:
JSON.stringify(
  Object.create(null, {
    x: { value: "x", enumerable: false },
    y: { value: "y", enumerable: true },
  }),
);

// "{"y":"y"}"

 七、手写浅拷贝和深拷贝

1.浅拷贝:

// 浅拷贝
let shalldowCopy = (obj) => {
    // 只拷贝引用类型
    if (typeof obj !== 'object' || obj == null) return
    let objCopy = obj instanceof Array ? [] : {}
    for (let key in obj){
        //不要隐式
        if (obj.hasOwnProperty(key)){
            objCopy[key] = obj[key]
        }
    }
    return objCopy
}


//测试
let obj = {
    name: '小黑子',
    age: 18,
    hobby: {
        type: 'coding'
    }
}
let arr = ['a', {n: 1}, 1, undefined, null]
let newObj = shalldowCopy(obj)
let newArr = shalldowCopy(arr)
obj.age = 20
obj.hobby.type = 'swimming'
arr[0] = 'b'
arr[1].n = 2
console.log(newObj); 
// { name: '小黑子', age: 18, hobby: { type: 'swimming' } }
console.log(newArr); 
// [ 'a', { n: 2 }, 1, undefined, null ]

2.深拷贝

let deepCopy = (obj) => {
    if(typeof obj!== 'object' || obj == null) return 
    let objCopy = obj instanceof Array ? [] : {}
    for (let key in obj){
        if(obj.hasOwnProperty(key)){
            // 与浅拷贝相比只是这里有差异其余原理都一样
            if(obj[key] instanceof Object){
                objCopy[key] = deepCopy(obj[key])
            } else {
                objCopy[key] = obj[key]
            }
        }
    }
    return objCopy
}



// 测试
const obj5 = {
    name:'你好',
    age:18,
    like:{
        type:'coding'
    }
}
const res = deepCopy(obj5)
console.log(res) // { name: '你好', age: 18, like: { type: 'coding' } }
obj5.like.type = 'sleeping'
console.log(res) // { name: '你好', age: 18, like: { type: 'coding' } }

  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值