JavaScript的浅拷贝和深拷贝

JavaScript中会用到深拷贝和浅拷贝的情况:使引用类型的使用互不影响。

简单了解一下基本类型和引用类型的区别:

  • 基本数据类型和引用类型的区别

基本数据类型: String,Boolean,Number,Undefined,Null;占用空间固定,保存在栈中。不管是进行赋值、浅拷贝、深拷贝都仅仅是把值赋值给对方,相互之间不受影响。如:

let a = 12; //=>undefined
let b = a; //赋值
b = 14; //=>14
a // =>12
b //=>14

引用类型 :array object function,引用类型是一种数据结构,用于将数据和功能组织在一起。占用空间不固定,保存在堆中;如果进行直接赋值的话,变量会指向同一个地址,当这个变量改变的时候,原变量也会受到影响。

如:

let person = {
    age:13
};
let person_1 = person;
person_1.age = 14;
person // =>{age: 14}

上述代码person是一个对象,同时也是一个引用类型,如果引用类型进行简单的赋值的话,如person_1,当进行修改person_1的时候,person对象也发生了改变。

划重点: 开发中我们真有需要“复制”一个这样的互不影响的引用类型,应该怎么做到呢?那就需要用到JavaScript中的浅拷贝和深拷贝来实现了。

这两者有什么的区别呢?

浅拷贝: 会得到一个新的变量,但是它仅仅只是复制了某个对象的头指针,并不改变子对象的指针,还存在共享同一块内存的子对象。

浅拷贝的方式:

1.Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

Object.assign(target, ...sources)

2.ES6

let target= {...sources};

如:

let person = {
    age:13,
    own:{
    phone:'ios'
    }
};
// Object.assign({},)
let person_1 = Object.assign({}, person);
person_1.age = 14;
person_1.own.phone= 'Android';
person // =>{age: 13, own: {phone:'Android'}}
//es6中可以这样实现浅拷贝
let person_2 = {...person};
person_2.own.phone = 'none';
person // =>{age: 13, own: {phone:'none'}}

从代码中可以看到子对象还互相影响。如果想要子对象也互不关联,那就需要用到深拷贝了。

深拷贝: 会拷贝创造出一个一模一样的对象,新旧对象不共享内存,修改新对象不会改到原对象。
实现方式:

  JSON.parse(JSON.stringify(object)) 

如:

let person = {
    age:13,
    own:{
    phone:'ios'
    }
};
let person_1 = JSON.parse(JSON.stringify(person));
person_1.age = 14;
person_1.own.phone='none';
person  //=>{age: 13, own: {phone: 'ios'}}

局限性:
会忽略 undefined : 如果原对象中,有属性的值是undefined,深拷贝的时候,会忽略掉。
如:

let person = {
    age:13,
    name:undefined,
    own:{
    phone:'ios'
    }
};

let person_1 = JSON.parse(JSON.stringify(person));
person_1 // =>{age: 13,own:{phone: "ios"}}
person //=>{age:13,name:undefined,own:{phone:"ios"}}

不能序列化函数:也就是不能使用JSON.parse()、JSON.stringify()进行转化的对象

不能解决循环引用的对象:对象内部属性的值 循环 利用内部其他属性的值。

  • JSON.parse(JSON.stringify(person))基本能够解决大部分问题,
  • 如果对象中含有上述问题不能进行深拷贝,可以尝试使用
    lodash.cloneDeep 进行深拷贝

lodash官网

  • 使用递归进行深拷贝
export function deepClone(obj) {
  let obj_1 = {};
  for (let key in obj) {
    if (Object.prototype.toString.call(obj[key]) === '[object Object]') {
      obj_1[key] = deepClone(obj[key]);
    } else {
      obj_1[key] = obj[key];
    }
  }
  return obj_1;
}

### JavaScript浅拷贝深拷贝的区别及实现方法 #### 1. 浅拷贝 浅拷贝是指创建一个新的对象,该对象拥有原始对象属性值的副本。然而,对于引用类型的属性(如数组或对象),仅复制其引用地址,而不是递归地复制嵌套的对象[^2]。 - **特点**:浅拷贝只复制对象的第一层属性,如果属性是引用类型,则新对象原对象共享这些引用类型的内存地址。 - **实现方式**: - 使用 `for...in` 循环手动复制属性。 - 使用 `Object.assign()` 方法。 - 使用扩展运算符 `...`。 ```javascript // 示例:使用 Object.assign 实现浅拷贝 const obj = { a: 1, b: { c: 2 } }; const shallowCopy = Object.assign({}, obj); shallowCopy.b.c = 3; console.log(obj.b.c); // 输出: 3 ``` 从上述代码可以看出,修改浅拷贝中的嵌套对象会影响原始对象,因为它们共享相同的引用地址。 #### 2. 深拷贝 深拷贝是指创建一个全新的对象,该对象不仅包含原始对象的所有属性值,还递归地复制了所有嵌套对象的值,确保新对象与原对象完全独立[^3]。 - **特点**:深拷贝会递归地复制对象的所有层级,即使对象中包含其他对象或数组,也会被完整复制,互不影响。 - **实现方式**: - 使用递归函数手动实现。 - 使用第三方库(如 Lodash 的 `cloneDeep` 方法)。 - 使用 `JSON.parse(JSON.stringify())` 方法(注意:这种方法无法处理函数、`undefined` 循环引用等特殊类型[^1])。 ```javascript // 示例:使用 JSON.parse(JSON.stringify()) 实现深拷贝 const obj = { a: 1, b: { c: 2 } }; const deepCopy = JSON.parse(JSON.stringify(obj)); deepCopy.b.c = 3; console.log(obj.b.c); // 输出: 2 [^1] ``` 从上述代码可以看出,修改深拷贝中的嵌套对象不会影响原始对象,因为它们之间没有共享任何引用。 #### 3. 区别总结 - **引用关系**:浅拷贝仅复制第一层属性,嵌套对象仍共享引用;深拷贝则递归地复制所有嵌套对象,确保完全独立[^3]。 - **性能**:浅拷贝通常比深拷贝更高效,因为它只需要复制一层引用,而不涉及递归操作[^2]。 - **适用场景**: - 浅拷贝适用于不需要修改嵌套对象或可以接受共享引用的场景。 - 深拷贝适用于需要完全独立的对象副本以避免副作用的场景。 #### 4. 注意事项 - `JSON.parse(JSON.stringify())` 方法虽然简单,但存在局限性,例如无法正确处理函数、`undefined` 循环引用等特殊类型[^1]。 - 在实际开发中,推荐使用成熟的第三方库(如 Lodash 的 `cloneDeep` 方法)来实现深拷贝,以避免潜在的问题。 ```javascript // 示例:使用 Lodash 的 cloneDeep 方法实现深拷贝 const _ = require('lodash'); const obj = { a: 1, b: { c: 2 } }; const deepCopy = _.cloneDeep(obj); deepCopy.b.c = 3; console.log(obj.b.c); // 输出: 2 [^3] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值