shallow copy vs deep clone

对象复制:分类讨论

1.可以用lodash

2.不能用库,可以用浏览器自带api,structuredClone

const obj1 = { a: 0, b: { c: 0 } };

const obj2 = Object.assign({}, obj1);

console.log(obj2); // { a: 0, b: { c: 0 } }

obj1.a = 1;

console.log(obj1); // { a: 1, b: { c: 0 } }

console.log(obj2); // { a: 0, b: { c: 0 } }

obj2.a = 2;

console.log(obj1); // { a: 1, b: { c: 0 } }

console.log(obj2); // { a: 2, b: { c: 0 } }

obj2.b.c = 3;

console.log(obj1); // { a: 1, b: { c: 3 } }

console.log(obj2); // { a: 2, b: { c: 3 } }

// Deep Clone

const obj3 = { a: 0, b: { c: 0 } };

const obj4 = structuredClone(obj3);

obj3.a = 4;

obj3.b.c = 4;

console.log(obj4); // { a: 0, b: { c: 0 } }

3.lodash深拷贝源码


浅拷贝:将B对象拷贝到A对象中,但不包括B里面的子对象

深拷贝:将B对象拷贝到A对象中,包括B里面的子对象

shallow copy vs deep clone

shallow copy of an object is a copy whose properties share the same references (point to the same underlying values) as those of the source object from which the copy was made. As a result, when you change either the source or the copy, you may also cause the other object to change too. That behavior contrasts with the behavior of a deep copy, in which the source and copy are completely independent.

More formally, two objects o1 and o2 are shallow copies if:

-They are not the same object (o1 !== o2).

-The properties of o1 and o2 have the same names in the same order.

-The values of their properties are equal.

-Their prototype chains are equal.

For shallow copies, only the top-level properties are copied, not the values of nested objects. Therefore:

-Re-assigning top-level properties of the copy does not affect the source object.

-Re-assigning nested object properties of the copy does affect the source object.

1. alteredTarget = Object.assign(tartget, source1,source2)

If the source value is a reference to an object, it only copies the reference value.

let obj1={a:0,b:{c:0}};

let obj2=Object.assign({},obj1);

console.log(JSON.stringify(obj2));// { "a": 0, "b": { "c": 0}}

obj1.a=1;

obj2.a=2;

obj2.b.c=3;

console.log(JSON.stringify(obj1));// { "a": 1, "b": { "c": 3}}

console.log(JSON.stringify(obj2));// { "a": 2, "b": { "c": 3}}

copies all enumerable own properties from one or more source objects to a target object. It returns the target object. Properties on the prototype chain and non-enumerable properties cannot be copied

Properties in the target object are overwritten by properties in the sources if they have the same key. Later sources' properties overwrite earlier ones.

The Object.assign() method only copies enumerable and own properties from a source object to a target object. It uses [[Get]] on the source and [[Set]] on the target, so it will invoke getters and setters. Therefore it assigns properties, versus copying or defining new properties. This may make it unsuitable for merging new properties into a prototype if the merge sources contain getters.

2. ...spread operator

In JavaScript, all standard built-in object-copy operations (spread syntaxArray.prototype.concat()Array.prototype.slice()Array.from()Object.assign(), and Object.create()) create shallow copies rather than deep copies.


deep copy of an object is a copy whose properties do not share the same references (point to the same underlying values) as those of the source object from which the copy was made. As a result, when you change either the source or the copy, you can be assured you're not causing the other object to change too. That behavior contrasts with the behavior of a shallow copy, in which changes to nested properties in the source or the copy may cause the other object to change too.

Two objects o1 and o2 are structurally equivalent if their observed behaviors are the same. These behaviors include:

-The properties of o1 and o2 have the same names in the same order.

-The values of their properties are structurally equivalent.

-Their prototype chains are structurally equivalent (although when we deal with structural equivalence, these objects are usually plain objects, meaning they both inherit from Object.prototype).

Structurally equivalent objects can either be the same object (o1 === o2) or copies (o1 !== o2). Because equivalent primitive values always compare equal, you cannot make copies of them.

We can now define deep copies more formally as:

-They are not the same object (o1 !== o2).

-The properties of o1 and o2 have the same names in the same order.

-The values of their properties are deep copies of each other.

-Their prototype chains are structurally equivalent.

Deep copies may or may not have their prototype chains copied (and often they do not). But two objects with structurally non-equivalent prototype chains (for example, one is an array and the other is a plain object) are never copies of each other.

One way to make a deep copy of a JavaScript object, if it can be serialized, is to use JSON.stringify() to convert the object to a JSON string, and then JSON.parse() to convert the string back into a (completely new) JavaScript object:

1. clone = JOSN.parse(JSON.stringify(obj))

const ingredientsList = ["noodles", { list: ["eggs", "flour", "water"] }];

const ingredientsListDeepCopy = JSON.parse(JSON.stringify(ingredientsList));

Because a deep copy shares no references with its source object, any changes made to the deep copy do not affect the source object.

// Change the value of the 'list' property in ingredientsListDeepCopy.

ingredientsListDeepCopy[1].list = ["rice flour", "water"];

// The 'list' property does not change in ingredients_list.

console.log(ingredientsList[1].list);

// Array(3) [ "eggs", "flour", "water" ]

序列化的时候遇到undefined和函数会跳过

2.web API structuredClone()

The web API structuredClone() also creates deep copies and has the advantage of allowing transferable objects in the source to be transferred to the new copy, rather than just cloned. It also handles more data types, such as Error. But note that structuredClone() isn't a feature of the JavaScript language itself — instead it's a feature of browsers and other JavaScript hosts that implement web APIs. And calling structuredClone() to clone a non-serializable object will fail in the same way that calling JSON.stringify() to serialize it will fail.


写一个深拷贝,只考虑基本数据类型和Object

对需要拷贝的对象的属性进行递归遍历,如果对象的属性不是基本类型时,就继续递归;遍历到对象属性为基本类型,将属性和属性值赋给新对象。

function deepClone(obj) {

    if(typeof obj !== 'object' || obj === null) return obj; //base

    let clone = Array.isArray(obj) ? [] : {};

    Object.keys(obj).forEach(key=> {

            clone[key]= typeof obj[key] === 'object' ? deepClone(obj[key]):obj[key]

    })

    return clone;

}


如何解决对象环绕的问题,例如a.b.a对象a的属性b指向的是a本身,这种情况如何实现深拷贝?

类型考虑全面

Number/String/Boolean/null/undefined

Object

Array、{}、Date

循环依赖(利用ES6的Map)

function是否可以深拷贝

闭包(因为function是有上下文的)


实现深度拷贝函数,并支持自定义拷贝

// target 为任意类型的值。

// customize 是一个函数,接受参数为深度拷贝过程中的属性(prop)、值(value),函数返回任意值作为当前属性的拷贝。

function deepCopy(target, customize) {

// your code

}

https://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,137评论 6 511
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,824评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,465评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,131评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,140评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,895评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,535评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,435评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,952评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,081评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,210评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,896评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,552评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,089评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,198评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,531评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,209评论 2 357

推荐阅读更多精彩内容