使用传播语法在 ES6 中进行深度复制
Deep copy in ES6 using the spread syntax
我正在尝试为我的 Redux 项目创建一个深度复制映射方法,该方法将使用对象而不是数组。我读到在 Redux 中每个状态都不应该改变以前的状态。
export const mapCopy = (object, callback) => {
return Object.keys(object).reduce(function (output, key) {
output[key] = callback.call(this, {...object[key]});
return output;
},
{});
}
有效:
return mapCopy(state, e => {
if (e.id === action.id) {
e.title = 'new item';
}
return e;
})
但是它不会深度复制内部项目,因此我需要将其调整为:
export const mapCopy = (object, callback) => {
return Object.keys(object).reduce(function (output, key) {
let newObject = {...object[key]};
newObject.style = {...newObject.style};
newObject.data = {...newObject.data};
output[key] = callback.call(this, newObject);
return output;
}, {});
}
这不太优雅,因为它需要知道传递了哪些对象。
ES6 有没有办法使用扩展语法来深拷贝一个对象?
ES6 built-in 没有这样的功能。我想你有几个选择取决于你想做什么。
如果真的要深拷贝:
- 使用图书馆。例如,lodash 有一个
cloneDeep
方法。
- 实现你自己的克隆功能。
您的特定问题的替代解决方案(无深拷贝)
不过,我认为,如果您愿意改变一些事情,您可以省去一些工作。我假设您控制了函数的所有调用站点。
指定传递给 mapCopy
的所有回调必须 return 新的 object,而不是改变现有的 object。例如:
mapCopy(state, e => {
if (e.id === action.id) {
return Object.assign({}, e, {
title: 'new item'
});
} else {
return e;
}
});
这利用 Object.assign
创建一个新的 object,在新 object 上设置 e
的属性,然后在新 object 上设置新标题=49=]。这意味着您永远不会改变现有的 objects 并且只在必要时创建新的。
mapCopy
现在可以很简单了:
export const mapCopy = (object, callback) => {
return Object.keys(object).reduce(function (output, key) {
output[key] = callback.call(this, object[key]);
return output;
}, {});
}
本质上,mapCopy
相信调用者会做正确的事。这就是为什么我说这假设您控制所有呼叫站点。
来自 MDN
Note: Spread syntax effectively goes one level deep while copying an array. Therefore, it may be unsuitable for copying multidimensional arrays as the following example shows (it's the same with Object.assign() and spread syntax).
就我个人而言,我建议使用 Lodash's cloneDeep 函数进行多级 object/array 克隆。
这是一个工作示例:
const arr1 = [{ 'a': 1 }];
const arr2 = [...arr1];
const arr3 = _.clone(arr1);
const arr4 = arr1.slice();
const arr5 = _.cloneDeep(arr1);
const arr6 = [...{...arr1}]; // a bit ugly syntax but it is working!
// first level
console.log(arr1 === arr2); // false
console.log(arr1 === arr3); // false
console.log(arr1 === arr4); // false
console.log(arr1 === arr5); // false
console.log(arr1 === arr6); // false
// second level
console.log(arr1[0] === arr2[0]); // true
console.log(arr1[0] === arr3[0]); // true
console.log(arr1[0] === arr4[0]); // true
console.log(arr1[0] === arr5[0]); // false
console.log(arr1[0] === arr6[0]); // false
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
对深拷贝使用JSON
var newObject = JSON.parse(JSON.stringify(oldObject))
var oldObject = {
name: 'A',
address: {
street: 'Station Road',
city: 'Pune'
}
}
var newObject = JSON.parse(JSON.stringify(oldObject));
newObject.address.city = 'Delhi';
console.log('newObject');
console.log(newObject);
console.log('oldObject');
console.log(oldObject);
function deepclone(obj) {
let newObj = {};
if (typeof obj === 'object') {
for (let key in obj) {
let property = obj[key],
type = typeof property;
switch (type) {
case 'object':
if( Object.prototype.toString.call( property ) === '[object Array]' ) {
newObj[key] = [];
for (let item of property) {
newObj[key].push(this.deepclone(item))
}
} else {
newObj[key] = deepclone(property);
}
break;
default:
newObj[key] = property;
break;
}
}
return newObj
} else {
return obj;
}
}
我经常用这个:
function deepCopy(obj) {
if(typeof obj !== 'object' || obj === null) {
return obj;
}
if(obj instanceof Date) {
return new Date(obj.getTime());
}
if(obj instanceof Array) {
return obj.reduce((arr, item, i) => {
arr[i] = deepCopy(item);
return arr;
}, []);
}
if(obj instanceof Object) {
return Object.keys(obj).reduce((newObj, key) => {
newObj[key] = deepCopy(obj[key]);
return newObj;
}, {})
}
}
// use: clone( <thing to copy> ) returns <new copy>
// untested use at own risk
function clone(o, m){
// return non object values
if('object' !==typeof o) return o
// m: a map of old refs to new object refs to stop recursion
if('object' !==typeof m || null ===m) m =new WeakMap()
var n =m.get(o)
if('undefined' !==typeof n) return n
// shallow/leaf clone object
var c =Object.getPrototypeOf(o).constructor
// TODO: specialize copies for expected built in types i.e. Date etc
switch(c) {
// shouldn't be copied, keep reference
case Boolean:
case Error:
case Function:
case Number:
case Promise:
case String:
case Symbol:
case WeakMap:
case WeakSet:
n =o
break;
// array like/collection objects
case Array:
m.set(o, n =o.slice(0))
// recursive copy for child objects
n.forEach(function(v,i){
if('object' ===typeof v) n[i] =clone(v, m)
});
break;
case ArrayBuffer:
m.set(o, n =o.slice(0))
break;
case DataView:
m.set(o, n =new (c)(clone(o.buffer, m), o.byteOffset, o.byteLength))
break;
case Map:
case Set:
m.set(o, n =new (c)(clone(Array.from(o.entries()), m)))
break;
case Int8Array:
case Uint8Array:
case Uint8ClampedArray:
case Int16Array:
case Uint16Array:
case Int32Array:
case Uint32Array:
case Float32Array:
case Float64Array:
m.set(o, n =new (c)(clone(o.buffer, m), o.byteOffset, o.length))
break;
// use built in copy constructor
case Date:
case RegExp:
m.set(o, n =new (c)(o))
break;
// fallback generic object copy
default:
m.set(o, n =Object.assign(new (c)(), o))
// recursive copy for child objects
for(c in n) if('object' ===typeof n[c]) n[c] =clone(n[c], m)
}
return n
}
const cloneData = (dataArray) => {
newData= []
dataArray.forEach((value) => {
newData.push({...value})
})
return newData
}
- a = [{名称:"siva"}, {名称:"siva1"}] ;
- b = myCopy(a)
- b === a // 假`
我自己昨天找到了这些答案,试图找到一种深度复制复杂结构的方法,其中可能包括递归链接。由于我对之前提出的任何建议都不满意,所以我自己实现了这个轮子。而且效果很好。希望对大家有帮助。
用法示例:
OriginalStruct.deep_copy = deep_copy; // attach the function as a method
TheClone = OriginalStruct.deep_copy();
请查看 https://github.com/latitov/JS_DeepCopy 以了解如何使用它的实例,还有 deep_print()。
如果你需要它,这里是 deep_copy() 函数的来源:
function deep_copy() {
'use strict'; // required for undef test of 'this' below
// Copyright (c) 2019, Leonid Titov, Mentions Highly Appreciated.
var id_cnt = 1;
var all_old_objects = {};
var all_new_objects = {};
var root_obj = this;
if (root_obj === undefined) {
console.log(`deep_copy() error: wrong call context`);
return;
}
var new_obj = copy_obj(root_obj);
for (var id in all_old_objects) {
delete all_old_objects[id].__temp_id;
}
return new_obj;
//
function copy_obj(o) {
var new_obj = {};
if (o.__temp_id === undefined) {
o.__temp_id = id_cnt;
all_old_objects[id_cnt] = o;
all_new_objects[id_cnt] = new_obj;
id_cnt ++;
for (var prop in o) {
if (o[prop] instanceof Array) {
new_obj[prop] = copy_array(o[prop]);
}
else if (o[prop] instanceof Object) {
new_obj[prop] = copy_obj(o[prop]);
}
else if (prop === '__temp_id') {
continue;
}
else {
new_obj[prop] = o[prop];
}
}
}
else {
new_obj = all_new_objects[o.__temp_id];
}
return new_obj;
}
function copy_array(a) {
var new_array = [];
if (a.__temp_id === undefined) {
a.__temp_id = id_cnt;
all_old_objects[id_cnt] = a;
all_new_objects[id_cnt] = new_array;
id_cnt ++;
a.forEach((v,i) => {
if (v instanceof Array) {
new_array[i] = copy_array(v);
}
else if (v instanceof Object) {
new_array[i] = copy_object(v);
}
else {
new_array[i] = v;
}
});
}
else {
new_array = all_new_objects[a.__temp_id];
}
return new_array;
}
}
干杯@!
const a = {
foods: {
dinner: 'Pasta'
}
}
let b = JSON.parse(JSON.stringify(a))
b.foods.dinner = 'Soup'
console.log(b.foods.dinner) // Soup
console.log(a.foods.dinner) // Pasta
使用JSON.stringify
和JSON.parse
是最好的方法。因为当 json 对象包含另一个对象时,通过使用扩展运算符我们将无法得到有效的答案。我们需要手动指定。
这里是处理所有基元、数组、对象、函数数据类型的 deepClone 函数
function deepClone(obj){
if(Array.isArray(obj)){
var arr = [];
for (var i = 0; i < obj.length; i++) {
arr[i] = deepClone(obj[i]);
}
return arr;
}
if(typeof(obj) == "object"){
var cloned = {};
for(let key in obj){
cloned[key] = deepClone(obj[key])
}
return cloned;
}
return obj;
}
console.log( deepClone(1) )
console.log( deepClone('abc') )
console.log( deepClone([1,2]) )
console.log( deepClone({a: 'abc', b: 'def'}) )
console.log( deepClone({
a: 'a',
num: 123,
func: function(){'hello'},
arr: [[1,2,3,[4,5]], 'def'],
obj: {
one: {
two: {
three: 3
}
}
}
}) )
这是我的深拷贝算法。
const DeepClone = (obj) => {
if(obj===null||typeof(obj)!=='object')return null;
let newObj = { ...obj };
for (let prop in obj) {
if (
typeof obj[prop] === "object" ||
typeof obj[prop] === "function"
) {
newObj[prop] = DeepClone(obj[prop]);
}
}
return newObj;
};
我建议使用展开运算符。如果您需要更新第二层,则需要进行第二次传播。如果旧对象中不存在地址,则尝试使用 newObject.address.city
之类的方式更新 newObject 将引发错误。
const oldObject = {
name: 'A',
address: {
street: 'Station Road',
city: 'Pune'
}
}
const newObject = {
...oldObject,
address: {
...oldObject.address,
city: 'Delhi'
}
}
console.log(newObject)
您可以像下面这样使用structuredClone()
:
const myOriginal = {
title: "Full Stack JavaScript Developer",
info: {
firstname: "Abolfazl",
surname: "Roshanzamir",
age: 33
}
};
const myDeepCopy = structuredClone(myOriginal);
structuredClone()
您可以使用 structuredClone()
,它是 built-in 函数,用于 deep-copying。
结构化克隆解决了 JSON.stringify()
技术的许多(虽然不是全部)缺点。
结构化克隆可以处理循环数据结构,
支持许多 built-in 数据类型,并且通常更健壮且通常更快。
但是,它仍然有一些限制,可能会让您感到困惑 off-guard:
1-Prototypes :如果将 structuredClone()
与 class 实例一起使用,
你会得到一个普通对象作为 return 值,因为结构化克隆会丢弃对象的原型链。
2-函数:如果你的对象包含函数,它们将被悄悄丢弃。
3- Non-cloneables:一些值不是结构化可克隆的,最显着的是错误和 DOM 节点。它会导致 structuredClone() 抛出。
const myDeepCopy = structuredClone(myOriginal);
JSON.stringify
如果您只是想将对象深复制到另一个对象,
您需要做的就是 JSON.stringify
对象,然后使用 JSON.parse
解析它。
这实际上将执行对象的深度复制。
let user1 = {
name: 'Abolfazl Roshanzamir',
age: 33,
university: {
name: 'Shiraz Bahonar University'
}
};
let user2 = JSON.parse(JSON.stringify(user1));
user2.name = 'Andy Madadian';
user2.university.name = 'Kerman Bahonar University'
console.log(user2);
// { name: 'Andy Madadian', age: 33, university: { name: 'Kerman Bahonar University' } }
console.log(user1);
// { name: 'Abolfazl Roshanzamir', age: 33, university: { name: 'Shiraz Bahonar University' } }
展开运算符/Object.assign()
在 JavaScript 中使用对象展开运算符创建浅表副本的一种方法...或 Object.assign()
如下所示:
const myShallowCopySpread = {...myOriginal};
const myShallowCopyObjectAssign=Object.assign({},obj)
性能
在谈到性能时,创建者 Surma 指出 JSON.Pars()
对于小对象可能会更快一些。但是当你有一个大的对象,复杂的对象
structuredClone()
开始明显变快。
Browser support 非常棒甚至得到 Node.js.
的支持
我正在尝试为我的 Redux 项目创建一个深度复制映射方法,该方法将使用对象而不是数组。我读到在 Redux 中每个状态都不应该改变以前的状态。
export const mapCopy = (object, callback) => {
return Object.keys(object).reduce(function (output, key) {
output[key] = callback.call(this, {...object[key]});
return output;
},
{});
}
有效:
return mapCopy(state, e => {
if (e.id === action.id) {
e.title = 'new item';
}
return e;
})
但是它不会深度复制内部项目,因此我需要将其调整为:
export const mapCopy = (object, callback) => {
return Object.keys(object).reduce(function (output, key) {
let newObject = {...object[key]};
newObject.style = {...newObject.style};
newObject.data = {...newObject.data};
output[key] = callback.call(this, newObject);
return output;
}, {});
}
这不太优雅,因为它需要知道传递了哪些对象。 ES6 有没有办法使用扩展语法来深拷贝一个对象?
ES6 built-in 没有这样的功能。我想你有几个选择取决于你想做什么。
如果真的要深拷贝:
- 使用图书馆。例如,lodash 有一个
cloneDeep
方法。 - 实现你自己的克隆功能。
您的特定问题的替代解决方案(无深拷贝)
不过,我认为,如果您愿意改变一些事情,您可以省去一些工作。我假设您控制了函数的所有调用站点。
指定传递给
mapCopy
的所有回调必须 return 新的 object,而不是改变现有的 object。例如:mapCopy(state, e => { if (e.id === action.id) { return Object.assign({}, e, { title: 'new item' }); } else { return e; } });
这利用
Object.assign
创建一个新的 object,在新 object 上设置e
的属性,然后在新 object 上设置新标题=49=]。这意味着您永远不会改变现有的 objects 并且只在必要时创建新的。mapCopy
现在可以很简单了:export const mapCopy = (object, callback) => { return Object.keys(object).reduce(function (output, key) { output[key] = callback.call(this, object[key]); return output; }, {}); }
本质上,mapCopy
相信调用者会做正确的事。这就是为什么我说这假设您控制所有呼叫站点。
来自 MDN
Note: Spread syntax effectively goes one level deep while copying an array. Therefore, it may be unsuitable for copying multidimensional arrays as the following example shows (it's the same with Object.assign() and spread syntax).
就我个人而言,我建议使用 Lodash's cloneDeep 函数进行多级 object/array 克隆。
这是一个工作示例:
const arr1 = [{ 'a': 1 }];
const arr2 = [...arr1];
const arr3 = _.clone(arr1);
const arr4 = arr1.slice();
const arr5 = _.cloneDeep(arr1);
const arr6 = [...{...arr1}]; // a bit ugly syntax but it is working!
// first level
console.log(arr1 === arr2); // false
console.log(arr1 === arr3); // false
console.log(arr1 === arr4); // false
console.log(arr1 === arr5); // false
console.log(arr1 === arr6); // false
// second level
console.log(arr1[0] === arr2[0]); // true
console.log(arr1[0] === arr3[0]); // true
console.log(arr1[0] === arr4[0]); // true
console.log(arr1[0] === arr5[0]); // false
console.log(arr1[0] === arr6[0]); // false
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
对深拷贝使用JSON
var newObject = JSON.parse(JSON.stringify(oldObject))
var oldObject = {
name: 'A',
address: {
street: 'Station Road',
city: 'Pune'
}
}
var newObject = JSON.parse(JSON.stringify(oldObject));
newObject.address.city = 'Delhi';
console.log('newObject');
console.log(newObject);
console.log('oldObject');
console.log(oldObject);
function deepclone(obj) {
let newObj = {};
if (typeof obj === 'object') {
for (let key in obj) {
let property = obj[key],
type = typeof property;
switch (type) {
case 'object':
if( Object.prototype.toString.call( property ) === '[object Array]' ) {
newObj[key] = [];
for (let item of property) {
newObj[key].push(this.deepclone(item))
}
} else {
newObj[key] = deepclone(property);
}
break;
default:
newObj[key] = property;
break;
}
}
return newObj
} else {
return obj;
}
}
我经常用这个:
function deepCopy(obj) {
if(typeof obj !== 'object' || obj === null) {
return obj;
}
if(obj instanceof Date) {
return new Date(obj.getTime());
}
if(obj instanceof Array) {
return obj.reduce((arr, item, i) => {
arr[i] = deepCopy(item);
return arr;
}, []);
}
if(obj instanceof Object) {
return Object.keys(obj).reduce((newObj, key) => {
newObj[key] = deepCopy(obj[key]);
return newObj;
}, {})
}
}
// use: clone( <thing to copy> ) returns <new copy>
// untested use at own risk
function clone(o, m){
// return non object values
if('object' !==typeof o) return o
// m: a map of old refs to new object refs to stop recursion
if('object' !==typeof m || null ===m) m =new WeakMap()
var n =m.get(o)
if('undefined' !==typeof n) return n
// shallow/leaf clone object
var c =Object.getPrototypeOf(o).constructor
// TODO: specialize copies for expected built in types i.e. Date etc
switch(c) {
// shouldn't be copied, keep reference
case Boolean:
case Error:
case Function:
case Number:
case Promise:
case String:
case Symbol:
case WeakMap:
case WeakSet:
n =o
break;
// array like/collection objects
case Array:
m.set(o, n =o.slice(0))
// recursive copy for child objects
n.forEach(function(v,i){
if('object' ===typeof v) n[i] =clone(v, m)
});
break;
case ArrayBuffer:
m.set(o, n =o.slice(0))
break;
case DataView:
m.set(o, n =new (c)(clone(o.buffer, m), o.byteOffset, o.byteLength))
break;
case Map:
case Set:
m.set(o, n =new (c)(clone(Array.from(o.entries()), m)))
break;
case Int8Array:
case Uint8Array:
case Uint8ClampedArray:
case Int16Array:
case Uint16Array:
case Int32Array:
case Uint32Array:
case Float32Array:
case Float64Array:
m.set(o, n =new (c)(clone(o.buffer, m), o.byteOffset, o.length))
break;
// use built in copy constructor
case Date:
case RegExp:
m.set(o, n =new (c)(o))
break;
// fallback generic object copy
default:
m.set(o, n =Object.assign(new (c)(), o))
// recursive copy for child objects
for(c in n) if('object' ===typeof n[c]) n[c] =clone(n[c], m)
}
return n
}
const cloneData = (dataArray) => {
newData= []
dataArray.forEach((value) => {
newData.push({...value})
})
return newData
}
- a = [{名称:"siva"}, {名称:"siva1"}] ;
- b = myCopy(a)
- b === a // 假`
我自己昨天找到了这些答案,试图找到一种深度复制复杂结构的方法,其中可能包括递归链接。由于我对之前提出的任何建议都不满意,所以我自己实现了这个轮子。而且效果很好。希望对大家有帮助。
用法示例:
OriginalStruct.deep_copy = deep_copy; // attach the function as a method
TheClone = OriginalStruct.deep_copy();
请查看 https://github.com/latitov/JS_DeepCopy 以了解如何使用它的实例,还有 deep_print()。
如果你需要它,这里是 deep_copy() 函数的来源:
function deep_copy() {
'use strict'; // required for undef test of 'this' below
// Copyright (c) 2019, Leonid Titov, Mentions Highly Appreciated.
var id_cnt = 1;
var all_old_objects = {};
var all_new_objects = {};
var root_obj = this;
if (root_obj === undefined) {
console.log(`deep_copy() error: wrong call context`);
return;
}
var new_obj = copy_obj(root_obj);
for (var id in all_old_objects) {
delete all_old_objects[id].__temp_id;
}
return new_obj;
//
function copy_obj(o) {
var new_obj = {};
if (o.__temp_id === undefined) {
o.__temp_id = id_cnt;
all_old_objects[id_cnt] = o;
all_new_objects[id_cnt] = new_obj;
id_cnt ++;
for (var prop in o) {
if (o[prop] instanceof Array) {
new_obj[prop] = copy_array(o[prop]);
}
else if (o[prop] instanceof Object) {
new_obj[prop] = copy_obj(o[prop]);
}
else if (prop === '__temp_id') {
continue;
}
else {
new_obj[prop] = o[prop];
}
}
}
else {
new_obj = all_new_objects[o.__temp_id];
}
return new_obj;
}
function copy_array(a) {
var new_array = [];
if (a.__temp_id === undefined) {
a.__temp_id = id_cnt;
all_old_objects[id_cnt] = a;
all_new_objects[id_cnt] = new_array;
id_cnt ++;
a.forEach((v,i) => {
if (v instanceof Array) {
new_array[i] = copy_array(v);
}
else if (v instanceof Object) {
new_array[i] = copy_object(v);
}
else {
new_array[i] = v;
}
});
}
else {
new_array = all_new_objects[a.__temp_id];
}
return new_array;
}
}
干杯@!
const a = {
foods: {
dinner: 'Pasta'
}
}
let b = JSON.parse(JSON.stringify(a))
b.foods.dinner = 'Soup'
console.log(b.foods.dinner) // Soup
console.log(a.foods.dinner) // Pasta
使用JSON.stringify
和JSON.parse
是最好的方法。因为当 json 对象包含另一个对象时,通过使用扩展运算符我们将无法得到有效的答案。我们需要手动指定。
这里是处理所有基元、数组、对象、函数数据类型的 deepClone 函数
function deepClone(obj){
if(Array.isArray(obj)){
var arr = [];
for (var i = 0; i < obj.length; i++) {
arr[i] = deepClone(obj[i]);
}
return arr;
}
if(typeof(obj) == "object"){
var cloned = {};
for(let key in obj){
cloned[key] = deepClone(obj[key])
}
return cloned;
}
return obj;
}
console.log( deepClone(1) )
console.log( deepClone('abc') )
console.log( deepClone([1,2]) )
console.log( deepClone({a: 'abc', b: 'def'}) )
console.log( deepClone({
a: 'a',
num: 123,
func: function(){'hello'},
arr: [[1,2,3,[4,5]], 'def'],
obj: {
one: {
two: {
three: 3
}
}
}
}) )
这是我的深拷贝算法。
const DeepClone = (obj) => {
if(obj===null||typeof(obj)!=='object')return null;
let newObj = { ...obj };
for (let prop in obj) {
if (
typeof obj[prop] === "object" ||
typeof obj[prop] === "function"
) {
newObj[prop] = DeepClone(obj[prop]);
}
}
return newObj;
};
我建议使用展开运算符。如果您需要更新第二层,则需要进行第二次传播。如果旧对象中不存在地址,则尝试使用 newObject.address.city
之类的方式更新 newObject 将引发错误。
const oldObject = {
name: 'A',
address: {
street: 'Station Road',
city: 'Pune'
}
}
const newObject = {
...oldObject,
address: {
...oldObject.address,
city: 'Delhi'
}
}
console.log(newObject)
您可以像下面这样使用structuredClone()
:
const myOriginal = {
title: "Full Stack JavaScript Developer",
info: {
firstname: "Abolfazl",
surname: "Roshanzamir",
age: 33
}
};
const myDeepCopy = structuredClone(myOriginal);
structuredClone()
您可以使用 structuredClone()
,它是 built-in 函数,用于 deep-copying。
结构化克隆解决了 JSON.stringify()
技术的许多(虽然不是全部)缺点。
结构化克隆可以处理循环数据结构,
支持许多 built-in 数据类型,并且通常更健壮且通常更快。
但是,它仍然有一些限制,可能会让您感到困惑 off-guard:
1-Prototypes :如果将 structuredClone()
与 class 实例一起使用,
你会得到一个普通对象作为 return 值,因为结构化克隆会丢弃对象的原型链。
2-函数:如果你的对象包含函数,它们将被悄悄丢弃。
3- Non-cloneables:一些值不是结构化可克隆的,最显着的是错误和 DOM 节点。它会导致 structuredClone() 抛出。
const myDeepCopy = structuredClone(myOriginal);
JSON.stringify
如果您只是想将对象深复制到另一个对象,
您需要做的就是 JSON.stringify
对象,然后使用 JSON.parse
解析它。
这实际上将执行对象的深度复制。
let user1 = {
name: 'Abolfazl Roshanzamir',
age: 33,
university: {
name: 'Shiraz Bahonar University'
}
};
let user2 = JSON.parse(JSON.stringify(user1));
user2.name = 'Andy Madadian';
user2.university.name = 'Kerman Bahonar University'
console.log(user2);
// { name: 'Andy Madadian', age: 33, university: { name: 'Kerman Bahonar University' } }
console.log(user1);
// { name: 'Abolfazl Roshanzamir', age: 33, university: { name: 'Shiraz Bahonar University' } }
展开运算符/Object.assign()
在 JavaScript 中使用对象展开运算符创建浅表副本的一种方法...或 Object.assign()
如下所示:
const myShallowCopySpread = {...myOriginal};
const myShallowCopyObjectAssign=Object.assign({},obj)
性能
在谈到性能时,创建者 Surma 指出 JSON.Pars()
对于小对象可能会更快一些。但是当你有一个大的对象,复杂的对象
structuredClone()
开始明显变快。
Browser support 非常棒甚至得到 Node.js.
的支持