preface

As front-end developers, when we are in the process of project development and overall planning, we often carry out object copy, array copy and other data operations for the JavaScript data transmitted from the back end, because it is helpful for data comparison and recovery. Copying JS data like this is called deep and shallow copying in JS. The recent spring recruitment interview has begun, presumably a large number of interviewers will investigate this basic knowledge, do you have a clear understanding of this knowledge point? Perhaps we often copy data, but may not be aware of the underlying principles, what is the difference between deep copy and shallow copy? Let’s find out! 🚗

The data type

In general, the problem of shallow and deep copying is essentially operating on variables that reference data types. If you want to get into this topic, you have to know something about JS data types. As you all know, data in JavaScript is usually divided into two types, basic data types and reference data types

Among them:

- Basic data types: Number, String, Null, Undefined, Boolean, Symbol - reference data types: obj,array,function...Copy the code

What are reference data types and what are primitive data types? This has to be generalizedJSThe memory mechanism is 😀

In JS, each piece of data requires one memory space. Memory space is divided into two types, stack and heap.

  • Stack: automatically distributed by the system, automatic recovery, high efficiency, but small capacity.
  • Heap: Manually allocated memory by the programmer, and manually destroyed, less efficient than stack, but large capacity.

In fact, it’s very simple. Primitive types are simple segments of data stored on the stack, while reference types refer to objects stored in the heap. JS, the basic data types is usually stored in the stack, it is because of these basic types in memory has a fixed to the size of the space, namely the value of a certain size, so these specific values are often stored in the stack space (except for closure), we can directly manipulate the value stored in the stack, such as literal meaning, this way of access for access by value.

The value size of reference types is not fixed, but their address size is fixed, so in order to store the type, the system will be able to access the address of the type on the stack, assign the value to the variable itself, and store its contents in the heap. Reference data is accessed like a pointer by accessing the address of the object in the stack and finding the specific contents of the object in the heap at that address.

Does this make any sense to you? The concept of shallow and deep copies is due to the way JS treats primitive types and reference types differently. We can access data types directly in stack memory, that is, manipulate the memory space directly, by value access. But for reference data, JS does not allow us to access it directly like the former. It seems that we are manipulating objects, but in fact we are just manipulating the reference of objects. The same is true for copying. If we want to copy a value of a basic data type, since it is simple data, we simply create the same amount of space in stack memory and store it in the new variable. In this way, the values are independent of each other, and modifying one variable does not affect the other variables. But for a copy of a reference type, the value we copy is no longer the value of the reference, but a pointer to that object. Both Pointers point to the same memory space, and if you manipulate the copied object, you affect the source object and the source data.

Var obj1={name:' yingying '} var obj2=obj1; Obj2. Name = 'green'; console.log('obj1.name',obj1.name); // 'Rhine' console.log('obj2.name',obj2.name); // 'yin-yin'Copy the code

😉 The above is a simple chestnut.

Shallow copy

What is shallow copy?

After talking about the difference between data types, we can finally introduce the way of copy. Shallow copy is actually copying Pointers to objects. In Baidu Encyclopedia, there is such an introduction:

The pointer to the target object and the pointer to the source object point to the same memory space. A shallow copy is a simple copy in which several objects share the same memory. However, when the memory is destroyed, all Pointers to this memory space need to be redefined, otherwise wild pointer errors will occur.

As you can see, shallow copy copies only the basic type of data or a pointer to an object, not the whole object. If the target object is modified, then the source object may be modified

Shallow copy implementation

Here are a few common ways to implement shallow copies

  • Object.assign()
var obj = { a: {a: "www", b: 39} };
var initalObj = 
Object.assign({}, obj);
initalObj.a.a = "yyy";
console.log(obj.a.a); 
//yyy
Copy the code

Note: There is a special case where an object is a deep copy if it has only one layer of attributes

let obj = {
    username: 'www'
};
let obj2 = Object.assign({},obj);
obj2.username = 'yyy';
console.log(obj); //{username: "www"}
Copy the code

  • Array.prototype.concat()
let arr = [1, 3, {    username: 'www'    }];
let arr2=arr.concat();    
arr2[2].username = 'yyy';
console.log(arr);
Copy the code

  • Array.prototype.slice()
let arr = [1, 3, {    username: ' www'    }];
let arr3 = arr.slice();
arr3[2].username = 'yyy'
console.log(arr);
Copy the code

Deep copy

What is deep copy?

If shallow copy doesn’t satisfy the needs of perfectionist developers, then deep copy is true copy! Unlike a shallow copy that copies only the object pointer, a deep copy creates an identical object. The new object and the source object do not interfere with each other, and modifying the new object does not affect the source object.

Deep copy implementation

At present, the implementation methods of deep copy mainly include recursive copy and JSON serialization

  • JSON. The parse () and JSON. Stringify ()
let obj = {
  name: 'yyy',
  age: 20,
  friend: {
    name: 'lll',
    age: 19
  }
};
let copyObj = JSON.parse(JSON.stringify(obj));
obj.name = 'aaa';
obj.friend.name = 'bbb';
console.log(obj);
console.log(copyObj);
Copy the code
  • recursive

Iterates through all reference values of an attribute until they are of a primitive type

function deepCopy(obj) { if (! obj && typeof obj ! == 'object') { throw new Error('error arguments'); } // const targetObj = obj.constructor === Array ? [] : {}; const targetObj = Array.isArray(obj) ? [] : {}; For (let key in obj) {if (obj. HasOwnProperty (key)) {if (obj[key] && typeof obj[key] === 'object') { targetObj[key] = deepCopy(obj[key]); } else { targetObj[key] = obj[key]; } } } return targetObj; }Copy the code

Refer to the article

www.cnblogs.com/secretAngel…

www.imooc.com/article/277…

conclusion

Although copy in JS is a very common operation, but still need to review often, if the article has wrong place also welcome to point out in the comments, thank you for reading!