前言
浅拷贝: 创建一个新对象,但只复制了原始对象的第一层属性,而不是递归地复制整个对象的所有嵌套属性。新对象中的嵌套对象仍然是原始对象中嵌套对象的引用,修改新对象中的嵌套对象会影响原始对象。
深拷贝: 创建一个全新的对象,同时递归地复制原始对象中的所有嵌套对象,使得新对象和原始对象完全独立,彼此不会互相影响。
理解: 一个对象只有一层而且没有引用类型(对象|数组)时,用浅拷贝的方法效果和深拷贝是一样的,因为对于基本数据类型(如数字、字符串等),新对象会复制它们的值而不是引用。
深拷贝实现
方法一: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 36 37 38 39
| 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);
|