前言
浅拷贝: 创建一个新对象,但只复制了原始对象的第一层属性,而不是递归地复制整个对象的所有嵌套属性。新对象中的嵌套对象仍然是原始对象中嵌套对象的引用,修改新对象中的嵌套对象会影响原始对象。
深拷贝: 创建一个全新的对象,同时递归地复制原始对象中的所有嵌套对象,使得新对象和原始对象完全独立,彼此不会互相影响。
理解: 一个对象只有一层而且没有引用类型(对象|数组)时,用浅拷贝的方法效果和深拷贝是一样的,因为对于基本数据类型(如数字、字符串等),新对象会复制它们的值而不是引用。
深拷贝实现
方法一:JSON.parse
1 2 3 4 5 6
| let target = { name: '小艾' } let source = { age: 20 } let deepClone = JSON.parse(JSON.stringify(target)) target.name = '小羊' console.log(target) console.log(deepClone)
|
方法二:lodash 的 cloneDeep
1 2
| import _ from 'lodash' const deepClone = _.cloneDeep(obj)
|
方法三:递归实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| export function deepClone(obj) { const _toString = Object.prototype.toString
if (!obj || typeof obj !== 'object') { return obj }
if (obj.nodeType && 'cloneNode' in obj) { return obj.cloneNode(true) }
if (_toString.call(obj) === '[object Date]') { return new Date(obj.getTime()) }
if (_toString.call(obj) === '[object RegExp]') { const flags = [] if (obj.global) flags.push('g') if (obj.multiline) flags.push('m') if (obj.ignoreCase) flags.push('i') return new RegExp(obj.source, flags.join('')) }
const result = Array.isArray(obj) ? [] : obj.constructor ? new obj.constructor() : {}
for (const key in obj) { result[key] = deepClone(obj[key]) }
return result }
|
浅拷贝实现
方法一:扩展运算符
1 2
| const original = { a: 1, b: 2 } const shallowCopy = { ...original }
|
方法二:Object.assign()
1 2
| const original = { a: 1, b: 2 } const shallowCopy = Object.assign({}, original)
|
方法三:Array.prototype.slice()(适用于数组)
1 2
| const originalArray = [1, 2, 3] const shallowCopyArray = originalArray.slice()
|
方法四:Array.prototype.concat()(适用于数组)
1 2
| const originalArray = [1, 2, 3] const shallowCopyArray = originalArray.concat()
|
Object.keys | values
Object.values 传入对象,返回对象 value 的数组集。
Object.keys 传入对象,返回对象 key 的数组集。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| const obj = { id: '1', name: '小维', }
const temp1 = [] Object.keys(obj).forEach((key) => { console.log(key) console.log(obj[key]) temp1.push(obj[key]) })
const temp2 = Object.values(obj) console.log(temp2) console.log(temp1) console.log(Object.keys(obj))
|
这两个方法还能处理数组和字符串,keys 返回索引,values 返回每个值拆开的数组。
1 2 3 4 5 6
| const str = 'abcde' const arr = ['a', 'b', 'c', 'd', 'e'] console.log(Object.keys(str)) console.log(Object.values(str)) console.log(Object.keys(arr)) console.log(Object.values(arr))
|
Object.assign
Object.assign(target, source_1, ···) 将后面的值赋值给前面的,并返回一个新的对象。
1 2 3 4 5 6 7 8 9 10
| let target = { name: '小艾 ' } let source = { age: 20 } let obj1 = Object.assign(target, source) console.log(source) console.log(obj1) source.name = '小维' let obj2 = Object.assign(target, source) console.log(obj2) console.log(obj1) console.log(target)
|
测试值变化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| const objN = { name: '坤', age: 24, info: { test: 'zz', }, } const test = { kun: 'ngm', } const newObjN = Object.assign(test, objN) console.log(test) console.log(newObjN) test.age = 26 objN.age = 25 console.log(newObjN) test.info.test = 'NN' console.log(objN) console.log(newObjN) console.log(test)
const original = { a: 1, b: 2, info: { name: '小维' }, arr: [1, 2, 3] } const shallowCopy = { ...original } console.log(shallowCopy)
shallowCopy.arr[0] = 34 console.log(original) console.log(shallowCopy)
|
扩展运算符测试
1 2 3 4 5 6 7
| const original = { a: 1, b: 2, info: { name: '小维' }, arr: [1, 2, 3] } const shallowCopy = { ...original }
shallowCopy.arr[0] = 34 console.log(original) console.log(shallowCopy)
|
Object.entries | fromEntries
Object.entries 将对象拆成数组,数组里包含多个小数组,每个小数组包含对象的 key 和 value。
Object.fromEntries 将上面的格式还原为对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| let target = { name: '小艾 ', age: 20 } let source = { age: 20 } const obj3 = { name: 'LUCKY', age: 20, } const arrLucky = Object.entries(obj3) console.log(arrLucky)
const obj4 = Object.fromEntries(arrLucky) console.log(obj4)
delete obj3.name console.log(obj3) let { name, ...params } = target console.log(params)
const objN = { name: '坤', age: 24, info: { test: 'zz', }, } const test = { kun: 'ngm', } const newObjN = Object.assign(test, objN) objN.age = 25 test.age = 26 test.info.test = 'NN' console.log(objN, newObjN, test) console.log(objN, newObjN, test)
const original = { a: 1, b: 2, info: { name: '小维' }, arr: [1, 2, 3] }
const shallowCopy = { ...original }
shallowCopy.arr[0] = 34 console.log(shallowCopy, original)
|