关于JS浅拷贝和深拷贝的理解
-
基础类型和引用类型
- 基础类型:存储在栈中,直接复制值,因此修改一个变量不会影响另一个变量。
- 引用类型:存储在堆中,栈中存储引用地址,浅拷贝会复制引用地址,因此修改一个对象的属性会影响另一个对象。
浅拷贝
浅拷贝的基本概念
-
基本数据类型:
- 如果属性是基本数据类型,浅拷贝会直接复制这些值。
- 例如,
let a = 1; let b = a;
,b
是a
的副本,修改b
不会影响a
。
-
引用类型:
- 如果属性是引用类型(如对象、数组),浅拷贝会复制引用地址。
- 例如,
let obj1 = { name: '张三' }; let obj2 = obj1;
,obj2
和obj1
引用同一个对象,修改obj2
的属性会影响obj1
。
- 浅拷贝的方法:
- Object.assign(target,source),它有两个特性
let oldObj = { name: '张三', age: { value: 18, }, } const newObj = Object.create(oldObj) newObj.ownProperty = 'ownProperty' let obj = {} Object.assign(obj, newObj) // 它不会拷贝对象的继承属性 console.log('====================================') console.log(obj, newObj) console.log('====================================')
let oldObj = { name: '张三', age: { value: 18, }, } Object.defineProperty(oldObj, 'nonEnumableProperty', { value: 'I am non-enumerable', enumerable: false, }) const newObj = Object.create(oldObj) newObj.ownProperty = 'ownProperty' let obj = {} Object.assign(obj, oldObj) // 它不会拷贝对象的不可枚举的属性 console.log('====================================') console.log(obj, oldObj) console.log('====================================')
-
扩展运算符、slice方法、concat方法
let oldObj = { name: '张三', age: { value: 18, }, } let newObj = { ...oldObj } console.log('====================================') console.log(newObj, oldObj) console.log('====================================') // 数组的浅拷贝 let arr = [1, 2, 3] let newArr1 = [...arr] let newArr2 = arr.slice() let newArr3 = arr.concat() console.log('====================================') console.log(arr, newArr1, newArr2, newArr3) console.log('====================================')
- 手写实现浅拷贝
export function shallowClone(params) { if (typeof params === 'object' && params !== null) { let newObj = Array.isArray(params) ? [] : {} // 遍历对象的所有可枚举属性包括继承的属性 for (let key in params) { // 过滤掉继承的属性,只复制对象自身的属性 if (params.hasOwnProperty(key)) { newObj[key] = params[key] } } return newObj } else { return params } }
- Object.assign(target,source),它有两个特性
深拷贝
深拷贝(Deep Copy) 是指创建一个新对象或数组,并递归地将原对象或数组中的所有属性和嵌套对象或数组也复制到新对象或数组中。深拷贝后,新对象或数组与原对象或数组完全独立,修改新对象或数组不会影响原对象或数组,反之亦然。
主要特点
-
独立性:
- 深拷贝创建的新对象或数组与原对象或数组完全独立,互不影响。
- 修改新对象或数组中的任何嵌套对象或数组不会影响原对象或数组。
-
递归复制:
- 深拷贝会递归地复制所有嵌套的对象和数组。
- 无论嵌套层级有多深,都会被完全复制。
-
处理复杂数据结构:
- 深拷贝能够处理包含复杂数据结构的对象或数组,如嵌套的对象、数组、函数、日期对象、正则表达式等。
实现深拷贝的方法
-
使用 JSON.parse(JSON.stringify(obj),优点
:简单易用。缺点:无法处理函数、undefined
、Symbol
、Date
对象、RegExp
对象等。let oldObj = { name: '张三', age: { value: 18, }, } let newObj = JSON.parse(JSON.stringify(oldObj)) newObj.age.value = 20 console.log('====================================') console.log(oldObj, newObj) console.log('====================================')
2.