JS - deep and shallow copy

Otong snail 2021-05-03 18:23:37
js deep shallow copy


The phenomenon

js True shallow copy refers to the reference data type .

Basic types :Number,String,Boolean,Null,Undefined ,Symbol
Reference type :Object,Array,Date,RegExp,Function

The reference type address is stored in the stack , Objects are actually stored in the heap . See the article for details js Function parameters are passed by value ?

Hierarchy

  • Shallow copy Only the attributes of the object are copied one by one , It doesn't replicate recursively , That is to say, only the first level attribute of the target object will be assigned .
  • Deep copy is different from shallow copy , It doesn't just copy the first layer properties of the target object , Instead, it recursively copies all the properties of the target object .

Whether to create a new heap for properties

  • Shallow copy is to create a new object , This object has an exact copy of the original object property values . If the attribute is a basic type , The copied values are the basic types , If the property is a reference type , Copy is the memory address , So if one of the objects changes the address , It will affect another object .
  • Deep copy is a complete copy of an object from memory , Open up a new area of heap memory for new objects , And modifying the new object does not affect the original object .

assignment , The difference between a shallow copy and a deep copy

  • When we assign an object to a new variable , What is assigned is actually the address of the object in the stack , Not the data in the pile . That is, two objects point to the same storage space , No matter which object changes , It's all about changing the contents of the storage space , therefore , The two objects are linked .
  • Shallow copy : Back in the heap Create memory , The basic data types of objects before and after copying do not affect each other , But the reference types of the objects before and after copying share the same block of memory , Will affect each other .
  • Deep copy : Open up a... From heap memory New areas Store new objects , Recursive copy of sub objects in an object , The two objects before and after copying do not affect each other .

var objOrigin = {
name: ' Er Dong snail ',
information: {
age: 27,
base: 'shanghai'
}
}
// Assignment operation 
var objAssignment = objOrigin;
// Shallow copy 
var objShallowCopy = Object.assign({}, objOrigin)
// Deep copy 
var objDeepCopy = JSON.parse(JSON.stringify(objOrigin))
 Copy code 

Memory view

image.png
image.png
image.png
image.png
image.png

Icon

image.png


Shallow copy

The way

Array

Array.concat

let array = [1, 2, {name: 'rodchen'}];
let arrayShallow = array.concat([]);
array[2].name = ' Er Dong snail ';
console.log(arrayShallow);
 Copy code 

Array.slice

let array = [1, 2, {name: 'rodchen'}];
let arrayShallow = array.slice(1);
array[2].name = ' Er Dong snail ';
console.log(arrayShallow);
 Copy code 

ES6 Extender

let array = [1, 2, {name: 'rodchen'}];
let arrayShallow = [...array];
array[2].name = ' Er Dong snail ';
console.log(arrayShallow);
 Copy code 

Array.map | Array.filter

let array = [1, 2, {name: 'rodchen'}];
let arrayMapShallow = array.map(item => item);
let arrayFilterShallow = array.filter(item => true);
array[2].name = ' Er Dong snail ';
console.log(arrayMapShallow);
console.log(arrayFilterShallow);
 Copy code 

object

Object.assign

let obj = {
age: 27,
information: {
name: 'rodchen'
}
}
let shallowObj = Object.assign({}, obj)
obj.information.name = ' Er Dong snail '
console.log(shallowObj)
 Copy code 

Object extenders

let obj = {
age: 27,
information: {
name: 'rodchen'
}
}
let shallowObj = {...obj}
obj.information.name = ' Er Dong snail '
console.log(shallowObj)
 Copy code 

Manual implementation

function cloneShallow(source) {
// Judge source Is it an object 
if (!(source instanceof Object)) {
return source;
}
var target = source instanceof Array ? [] : {};
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
return target;
}
 Copy code 



Deep copy

The way

JSON parse and stringify Method

  • undefined、 Any function 、 Regular expression types and symbol value , It is ignored during serialization ( When it appears in a property value of a non array object ) Or be converted into null( When it appears in an array );
  • It's going to abandon the object constructor. After the deep copy , No matter what the original constructor of this object is , After deep copy, it will become Object;
  • If there is a circular reference in the object, it cannot be handled correctly .

Manual implementation

The initial release


function cloneDeep(source) {
// Judge source Is it an object 
if (!(source instanceof Object)) {
return source;
}
var target = source instanceof Array ? [] : {};
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source instanceof Object ? cloneDeep(source[key]) : source[key];
}
}
return target;
}
 Copy code 
let array = [1, 2, {name: 'rodchen'}];
let arrayShallow = cloneDeep(array);
array[2].name = ' Er Dong snail ';
console.log(arrayShallow); // Array [1, 2, Object { name: "rodchen" }]
let obj = {
age: 27,
information: {
name: 'rodchen'
}
}
let shallowObj = cloneDeep(obj)
obj.information.name = ' Er Dong snail '
console.log(shallowObj) // Object { age: 27, information: Object { name: "rodchen" } }
 Copy code 

Circular reference

In the following example , We use recycled applications , Perform the above method , Report stack overflow .

let array = [1, 2];
array[2] = array
let arrayShallow = cloneDeep(array); // Error: Maximum call stack size exceeded
array[2].name = ' Er Dong snail ';
console.log(arrayShallow);
let obj = {
age: 27,
}
obj.information = obj
let shallowObj = cloneDeep(obj) // Error: Maximum call stack size exceeded
obj.information.name = ' Er Dong snail '
console.log(shallowObj)
 Copy code 
function cloneDeep(source, hash = new WeakMap()) {
// Judge source Is it an object 
if (!(source instanceof Object)) {
return source;
}
if (hash.get(source)) return hash.get(source);
var target = source instanceof Array ? [] : {};
hash.set(source, target);
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source instanceof Object ? cloneDeep(source[key], hash) : source[key];
}
}
return target;
}
 Copy code 

there weakMap Can pass ES5 Array instead of .


Adaptation method , date , Regular

function cloneDeep(source, hash = new WeakMap()) {
// Judge source Is it an object 
if (!(source instanceof Object)) {
return source;
}
if (source instanceof Function) return new Function("return " + source.toString())();
if (source instanceof Date) return new Date(source);
if (source instanceof RegExp) return new RegExp(source);
if (hash.get(source)) return hash.get(source);
var target = source instanceof Array ? [] : {};
hash.set(source, target);
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source instanceof Object ? cloneDeep(source[key], hash) : source[key];
}
}
return target;
}
 Copy code 

The third party

  • Underscore —— _.clone():
 This method is actually a kind of shallow replication (shallow-copy)
 Copy code 
  • jQuery —— . c l o n e ( ) / .clone() / .extend():
 stay jQuery There is also such a person named $.clone() Methods , But it's not for ordinary JS Deep copies of objects , But for DOM object .
And Underscore similar , We can also pass $.extend() Method to complete the deep copy .
thankfully , We are jQuery You can add a parameter to recursion extend.
call $.extend(true, {}, ...) You can achieve deep replication .
 Copy code 
  • lodash —— _.clone() / _.cloneDeep():
 stay lodash There are two ways to copy in , Namely _.clone() and _.cloneDeep().
among _.clone(obj, true) Equivalent to _.cloneDeep(obj)
 Copy code 
// npm install --save @jsmini/clone
import { clone, cloneJSON, cloneLoop, cloneForce } from '@jsmini/clone';
 Copy code 



reference

segmentfault.com/a/119000001…
segmentfault.com/a/119000001…
jerryzou.com/posts/dive-…
juejin.cn/post/684490…

版权声明
本文为[Otong snail]所创,转载请带上原文链接,感谢
https://qdmana.com/2021/05/20210503181828427R.html

  1. CSS layout
  2. Application scenario explanation of Vue dynamic component
  3. Redux learning notes 04 -- using multiple reducers to manage data
  4. After three months of typescript writing, what have I learned?
  5. Node family - what is a callback?
  6. React -- a simple implementation of render & create element
  7. JS learning simple usage of jquery
  8. Seamless love
  9. 小白前端入门笔记(12),设置哑链接
  10. Small white front-end entry notes (12), set dumb links
  11. Vue2. X opens composition API and TSX
  12. Interview record and thinking of social recruitment for one and a half years (Alibaba, Tencent, baidu offer)
  13. Flex learning notes
  14. The most essential closure article in the eastern hemisphere
  15. 2021-05-03 hot news
  16. Sword finger offer -- reverse order pair in array (JS Implementation)
  17. Working process of scaffold
  18. Use decorator mode to strengthen your fetch
  19. [JS] scope (Introduction)
  20. Employment information statistics network (interface document)
  21. Analysis of MVC
  22. [middle stage] please stay and join me in the backstage
  23. Understanding front end garbage collection
  24. [continuous update] front end special style implementation
  25. Flutter product analysis and package reduction scheme
  26. XPath positioning
  27. 前端开发css中的flex布局的使用
  28. The use of flex layout in front end development CSS
  29. JQuery核心函数和静态方法
  30. JQuery core functions and static methods
  31. Node family - understanding of blocking and non blocking
  32. 热点微前端Microfrontend的讨论:谷歌AdWords是真实的微前端
  33. Vue source code analysis (2) initproxy initialization proxy
  34. What's TM called react diff
  35. Summary of common front end data structure
  36. Useeffect in hooks
  37. [encapsulation 02 design pattern] Command pattern, share meta pattern, combination pattern, proxy pattern, strategy pattern
  38. Front end notes: virtual Dom and diff of vue2. X
  39. The best code scanning plug-in of flutter
  40. The simplest plug-in for rights management of flutter
  41. 21. Object oriented foundation "problems and solutions of object traversal"
  42. Discussion on hot micro front end: Google AdWords is a real micro front end
  43. Usecallback and usememo for real performance optimization
  44. 【前端圭臬】十一:从规范看 JavaScript 执行上下文(下)
  45. [front end standard] 11: Javascript execution context from the perspective of specification (2)
  46. Hexagonal六角形架构ReactJS的实现方式 - Janos Pasztor
  47. Transaction of spring's reactive / imperative relational database
  48. The implementation of hexagonal hexagonal reactjs Janos pasztor
  49. HTTP状态码:402 Payment Required需要付款 - mozilla
  50. HTTP status code: 402 payment required - Mozilla
  51. Factory mode, constructor mode and prototype mode
  52. Build the scaffold of react project from scratch (Series 1: encapsulating a request method with cache function based on Axios)
  53. Cocos Quick Start Guide
  54. Comparison of three default configurations of webpack5 modes
  55. A case study of the combination of flutter WebView and Vue
  56. CSS: BFC and IFC
  57. A common error report and solution in Vue combat
  58. JS: this point
  59. JS: prototype chain
  60. JavaScript series -- promise, generator, async and await