浅拷贝与深拷贝

时间:2021-2-20 作者:admin

浅拷贝 vs 深拷贝

  • 浅拷贝: 创建一个新对象, 这个对象有着原始对象属性值的一份精确拷贝, 如果属性是基本类型, 拷贝该基本类型的值, 如果属性是引用类型, 拷贝该引用类型的内存地址. 如果一个对象改变了这个地址, 就会影响到另一个对象.
  • 深拷贝: 将一个对象从内存中完整拷贝一份出来, 从堆内存中开辟一个新的区域存放新对象, 且修改新对象不会影响原对象.

    浅拷贝与深拷贝

赋值

// 对象赋值let obj1 = {    name : 'A',    arr : [1,[2,3],4],};let obj2 = obj1;obj2.name = "B";obj2.arr[1] = [5,6,7];console.log('obj1',obj1); // obj1 {name: 'B', arr: [1,[5,6,7],4]}console.log('obj2',obj2); // obj2 {name: 'B', arr: [1,[5,6,7],4]}

浅拷贝

// 浅拷贝let obj1 = {    name : 'A',    arr : [1,[2,3],4],};let obj3 = shallowClone(obj1);obj3.name = "B";obj3.arr[1] = [5,6,7]; // 新旧对象还是共享同一块内存// 这是个浅拷贝的方法function shallowClone(source) {    var target = {};    for (var i in source) {        if (source.hasOwnProperty(i)) {            target[i] = source[i];        }    }    return target;}console.log('obj1',obj1); // obj1 {name: 'A', arr: [1,[5,6,7],4]}console.log('obj3',obj3); // obj3 {name: 'B', arr: [1,[5,6,7],4]}

深拷贝

// 深拷贝let obj1 = {    name: 'A',    arr: [1,[2,3],4],};let obj4 = deepClone(obj1);obj4.name = "B";obj4.arr[1] = [5,6,7]; // 新对象跟原对象不共享内存// 这是个深拷贝的方法function deepClone(obj) {    if (obj === null) return obj;     if (obj instanceof Date) return new Date(obj);    if (obj instanceof RegExp) return new RegExp(obj);    if (typeof obj !== "object") return obj;    let cloneObj = new obj.constructor();    for (let key in obj) {      if (obj.hasOwnProperty(key)) {        // 实现一个递归拷贝        cloneObj[key] = deepClone(obj[key]);      }    }    return cloneObj;}console.log('obj1',obj1); // obj1 {name: 'A', arr:[1,[2,3], 4]}console.log('obj4',obj4); // obj4 {name: 'B', arr:[1,[5,6,7], 4]}

赋值, 浅拷贝, 深拷贝的对比

浅拷贝与深拷贝

浅拷贝的实现方式

  1. Object.assign(): 把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象.
let obj1 = { person: {name: "Messi", age: 33}, club: 'Barcelona' };let obj2 = Object.assign({}, obj1);obj2.person.name = "Suarez";obj2.club = 'Atlético Madrid';console.log(obj1); // { person: { name: 'Suarez', age: 33 }, club: 'Barcelona' }
  1. 函数库lodash的_.clone方法
var _ = require('lodash');var obj1 = {    a: 1,    b: { f: { g: 1 } },    c: [1, 2, 3]};var obj2 = _.clone(obj1);console.log(obj1.b.f === obj2.b.f); // true
  1. 展开运算符…
let obj1 = { name: 'Messi', address:{ x: 100, y: 100 } } let obj2 = {... obj1}obj1.address.x = 200;obj1.name = 'Suarez';console.log('obj2', obj2); // obj2 { name: 'Messi', address: { x: 200, y: 100 } }
  1. Array.prototype.concat()
let arr = [ 1, 3, { username: 'Messi' } ];let arr2 = arr.concat();arr2[2].username = 'Suarez';console.log(arr); // [ 1, 3, { username: 'Suarez' } ]
  1. Array.prototype.slice()
let arr = [1, 3, { username: 'Messi' } ];let arr3 = arr.slice();arr3[2].username = 'Suarez'console.log(arr); // [ 1, 3, { username: 'Suarez' } ]

深拷贝的实现方式

  1. JSON.parse(JSON.stringify()): 利用JSON.stringify将对象转成JSON字符串, 再用JSON.parse把字符串解析成对象, 一去一来, 新的对象产生了, 而且对象会开辟新的栈, 实现深拷贝(不能处理函数和正则)
let arr1 = [1, 3, { username: 'Messi' }, function(){} ];let arr2 = JSON.parse(JSON.stringify(arr1));arr2[2].username = 'Suarez';
  1. 函数库lodash的_.cloneDeep方法
var _ = require('lodash');var obj1 = {    a: 1,    b: { f: { g: 1 } },    c: [1, 2, 3]};var obj2 = _.cloneDeep(obj1);console.log(obj1.b.f === obj2.b.f); // false
  1. jQuery.extend()方法
$.extend(deepCopy, target, object1, [objectN]) // 第一个参数为true, 就是深拷贝
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。