主页 > 创业  > 

数组和对象深浅拷贝

数组和对象深浅拷贝
对象浅拷贝 方法一:使用 Object.assign()

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

const originalObj = { name: 'John', age: 30, hobbies: ['reading', 'running'] }; const shallowCopy = Object.assign({}, originalObj); console.log(shallowCopy); // 修改浅拷贝对象的基本类型属性 shallowCopy.name = 'Jane'; console.log(originalObj.name); // John console.log(shallowCopy.name); // Jane // 修改浅拷贝对象的引用类型属性 shallowCopy.hobbies.push('swimming'); console.log(originalObj.hobbies); // ['reading', 'running', 'swimming'] console.log(shallowCopy.hobbies); // ['reading', 'running', 'swimming'] 方法二:使用扩展运算符(...)

扩展运算符可以将一个对象或数组展开。

const originalObj = { name: 'John', age: 30, hobbies: ['reading', 'running'] }; const shallowCopy = {...originalObj }; console.log(shallowCopy); // 修改浅拷贝对象的基本类型属性 shallowCopy.name = 'Jane'; console.log(originalObj.name); // John console.log(shallowCopy.name); // Jane // 修改浅拷贝对象的引用类型属性 shallowCopy.hobbies.push('swimming'); console.log(originalObj.hobbies); // ['reading', 'running', 'swimming'] console.log(shallowCopy.hobbies); // ['reading', 'running', 'swimming'] 方法三:使用Object.create() let a = { name: '艾总', like: { n: 'running' } } let b = Object.create(a) a.name = '黎总' console.log(a); console.log(b); console.log(b.name); //{ name: '黎总', like: { n: 'running' } } //{} //黎总 数组浅拷贝 方法一:[].concat(arr) let arr = [1, 2, 3, { a: 10 }] let newArr = [1, 2].concat(arr) arr[3].a = 100 console.log(arr); console.log(newArr); //[ 1, 2, 3, { a: 100 } ] //[ 1, 2, 1, 2, 3, { a: 100 } ] 方法二:arr.slice(0) arr = [1, 2, 3, 4, 5, { age: 18 }] const arr1 = arr.slice(0) arr[5].age = 20 console.log(arr); console.log(arr1); //[ 1, 2, 3, 4, 5, { age: 20 } ] //[ 1, 2, 3, 4, 5, { age: 20 } ] 方法三:arr.toReversed().reverse() arr = [1, 2, 3, 4, 5, { age: 18 }] const arr1 = arr.toReversed().reverse() arr[5].age = 20 console.log(arr); console.log(arr1); //[ 1, 2, 3, 4, 5, { age: 20 } ] //[ 1, 2, 3, 4, 5, { age: 20 } ] 方法四:使用扩展运算符(...)

扩展运算符可以将一个对象或数组展开。

对象深拷贝 方法一:使用 JSON.parse(JSON.stringify())

这是一种简单的深拷贝方法,但有一些局限性,比如不能处理函数、Symbol 类型的属性和 Date 对象等。

const originalObj = { name: 'John', age: 30, hobbies: ['reading', 'running'] }; const deepCopy = JSON.parse(JSON.stringify(originalObj)); console.log(deepCopy); // 修改深拷贝对象的基本类型属性 deepCopy.name = 'Jane'; console.log(originalObj.name); // John console.log(deepCopy.name); // Jane // 修改深拷贝对象的引用类型属性 deepCopy.hobbies.push('swimming'); console.log(originalObj.hobbies); // ['reading', 'running'] console.log(deepCopy.hobbies); // ['reading', 'running', 'swimming'] 方法二:自定义递归函数

通过递归遍历对象的所有属性,复制每个属性的值。

使用typeof检测引用数据类型(如对象、数组、函数等)时,除了函数会返回 'function' 外,其他的引用数据类型都会返回 'object'。

function deepClone(obj) { // 使用typeof检测引用数据类型(如对象、数组、函数等)时, // 除了函数会返回 'function' 外,其他的引用数据类型都会返回 'object'。 //typeof 数组 会返回'object' //typeof 无法细致区分不同类型的引用数据,所以统一将数组归类为 'object'。 if (typeof obj !== 'object' || obj === null) { //后续调用deepClone方法时如果是基本数据类型,会直接返回!!! return obj } let clone; if (Array.isArray(obj)) { clone = []; for (let i = 0; i < obj.length; i++) { clone[i] = deepClone(obj[i]); } } else { //进入这里代表obj是一个对象,对对象进行深拷贝时必须确保拷贝的属性是当前对象自身的属性 clone = {} // 使用 for...in 循环进行遍历时,会遍历到对象原型链上的可枚举属性。 for (let key in obj) { //所以使用obj.hasOwnProperty(key)进行确认 if (obj.hasOwnProperty(key)) { clone[key] = deepClone(obj[key]) } } } return clone; } const originalObj = { name: 'John', age: 30, hobbies: ['reading', 'running'] }; const deepCopy = deepClone(originalObj); console.log(deepCopy); // 修改深拷贝对象的基本类型属性 deepCopy.name = 'Jane'; console.log(originalObj.name); // John console.log(deepCopy.name); // Jane // 修改深拷贝对象的引用类型属性 deepCopy.hobbies.push('swimming'); console.log(originalObj.hobbies); // ['reading', 'running'] console.log(deepCopy.hobbies); // ['reading', 'running', 'swimming'] 注意事项 虽然 for...in 会遍历原型链上的可枚举属性,但现代 JavaScript 中很多内置对象的原型属性是不可枚举的,比如 Object.prototype 上的方法(toString、hasOwnProperty 等),所以 for...in 通常不会遍历到这些方法。for...in 遍历属性的顺序是不确定的,不同的 JavaScript 引擎可能会有不同的实现,所以不要依赖 for...in 的遍历顺序。
标签:

数组和对象深浅拷贝由讯客互联创业栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“数组和对象深浅拷贝