“This is the sixth day of my participation in the First Challenge 2022. For details: First Challenge 2022”
Introduction to the
Interview can be JS assignment copy, shallow copy, deep copy of the problem is very few. Today I review again, I hope to help you.
variable
To understand shallow and deep copy in JS, you need to be familiar with variable types, which are divided into basic data types (value types) and reference data types (complex data types). Values for basic data types are stored directly in stack memory, whereas stack memory for reference data types holds memory addresses and values are stored in heap memory.
Basic data types include Number, String, Boolean, Null, Undefined, Symbol, BigInt, and reference data types include Object, Array, Date, Error, Function, and RegExp.
The storage for reference data types is shown below
Copy assignment
Assignment copy is what we usually call = assignment. Assignment copies are divided into basic data type assignment copies and reference data type assignment copies.
Assignment copies of primitive data types do not affect each other.
let name = "randy";
let name2 = name; // Assign name to name2
name = "demi"; // Change name to 'demi'
console.log(name); // demi
console.log(name2); // randy
Copy the code
An assignment copy of a reference data type is an address reference, meaning that two variables refer to the same address in heap memory, so they have an effect on each other.
const user = { name: "randy" };
const user2 = user;
user.name = "demi";
console.log(user.name); // demi
console.log(user2.name); // demi
Copy the code
What if I don’t want to refer to copies of data types affecting each other? We need to use our shallow copy deep copy knowledge. Shallow copy and deep copy apply only to reference data. Basic data types do not have shallow copy and deep copy.
Shallow copy
Shallow copy copies only the first layer properties of the original object. That is, if the property is a primitive data type, the value of the primitive type is copied. If the attribute is a reference data type, the memory address of the reference type is copied.
Implement shallow copy manually
// Shallow copy obj
const shallowCopy = (obj) = > {
if (typeof obj === 'object'&& obj ! = =null) {
let copy = Array.isArray(obj) ? [] : {};
// Iterate over the old object/array, assigning the first level property to the new object/array
for (var p in obj) {
copy[p] = obj[p]
}
// The new object returned is the shallow-copied object
return copy
} else {
// If it is a basic type, return it directly
return obj
}
}
Copy the code
The shallow copy method is commonly used
Common shallow copy methods in JS include object.assign (), extension operator {… Obj} and Array array.concat (), array.slice (), array.from (), extension operator {… Clone methods for arR} and Lodash libraries.
So let me give you an example
const user = {
name: "randy".address: { province: "Hunan".city: "Mimi,"}};const user2 = Object.assign({}, user);
constuser3 = { ... user }; user.name ="demi";
user.address.province = "Shanghai";
console.log("user:", user); / / {name: "demi, address: {province: 'Shanghai, city:' mi - ronaldo '}}
console.log("user2:", user2); / / {name: "randy", address: {province: 'Shanghai, city:' mi - ronaldo '}}
console.log("user3:", user3); / / {name: "randy", address: {province: 'Shanghai, city:' mi - ronaldo '}}
const arr = ["randy", { province: "Hunan".city: "Mimi," }];
const arr2 = arr.concat([]);
const arr3 = arr.slice();
const arr4 = Array.from(arr);
const arr5 = [...arr];
arr[0] = "demi";
arr[1].province = "Shanghai";
console.log("arr:", arr); / / {name: "demi, address: {province: 'Shanghai, city:' mi - ronaldo '}}
console.log("arr2:", arr2); / / {name: "randy", address: {province: 'Shanghai, city:' mi - ronaldo '}}
console.log("arr3:", arr3); / / {name: "randy", address: {province: 'Shanghai, city:' mi - ronaldo '}}
console.log("arr4:", arr4); / / {name: "randy", address: {province: 'Shanghai, city:' mi - ronaldo '}}
console.log("arr5:", arr5); / / {name: "randy", address: {province: 'Shanghai, city:' mi - ronaldo '}}
Copy the code
Deep copy
To solve the shallow copy problem will use our deep copy!
A deep copy is a complete copy of the object in memory, creating a new memory space in the heap, completely independent of the original object. Modifying the new object does not affect the original object.
Implement deep copy manually
// Recursive shallow copy
const _shallowCopy = (obj) = > {
const copy = Array.isArray(obj) ? [] : {};
for (let p in obj) {
if (typeof obj[p] === "object") {
// Object type, continue recursive shallow copy
copy[p] = _shallowCopy(obj[p]);
} else{ copy[p] = obj[p]; }}return copy;
};
/ / copy
const deepCopy = (obj) = > {
if (typeof obj === "object"&& obj ! = =null) {
// If it is a reference type, make a recursive shallow copy
return _shallowCopy(obj);
} else {
// If it is a basic type, return it directly
returnobj; }};Copy the code
The deep-copy method is commonly used
Parse (json.stringfy (obj)) or the deepClone method of the LoDash library.
So let me give you an example
/ / object
const user = {
name: "randy".address: { province: "Hunan".city: "Mimi,"}};const user2 = JSON.parse(JSON.stringify(user));
user.name = "demi";
user.address.province = "Shanghai";
console.log("user:", user); / / {name: "demi, address: {province: 'Shanghai, city:' mi - ronaldo '}}
console.log("user2:", user2); / / {name: "randy", address: {province: 'in hunan province, city,' Mimi ROM '}}
/ / array
const arr = ["randy", { province: "Hunan".city: "Mimi," }];
const arr2 = JSON.parse(JSON.stringify(arr));
arr[0] = "demi";
arr[1].province = "Shanghai";
console.log("arr", arr); / / {name: "demi, address: {province: 'Shanghai, city:' mi - ronaldo '}}
console.log("arr2", arr2); / / {name: "randy", address: {province: 'in hunan province, city,' Mimi ROM '}}
Copy the code
extension
Parse (json.stringfy (obj)) is useful, but there are a few points to note
undefined
,Arbitrary function
As well assymbol
Value is ignored during serialization (when it appears in an attribute value of a non-array object) or is converted tonull
(when appearing in an array).function
,undefined
,Symbol
Returns when converted separatelyundefined
.- All to
symbol
Properties that are property keys are completely ignored. Date
Date is calledtoJSON()
Convert it tostring
String (same asDate.toISOString()
), so it is treated as a string.- The error object is converted to an empty object.
- The re is converted to an empty object.
NaN
和Infinity
The value of the format andnull
Will be regarded asnull
.- Executing this method on objects that contain circular references (objects that refer to each other in an infinite loop) throws an error.
- When trying to switch
BigInt
The value of the type is thrownTypeError ("BigInt value can't be serialized in JSON"
).
Undefined, arbitrary functions, and symbol values are ignored during serialization (when appearing in an attribute value of a non-array object) or converted to NULL (when appearing in an array).
const obj4 = {
a: undefined.b: function say() {},
c: Symbol(123),};const str4 = JSON.stringify(obj4);
console.log(str4); / / {}
const obj5 = [undefined.function say() {}, Symbol(123)];
const str5 = JSON.stringify(obj5);
console.log(str5); // [null,null,null]
Copy the code
Function, undefined, and Symbol are converted separately to return undefined.
console.log(
JSON.stringify(Symbol(123)),
JSON.stringify(undefined),
JSON.stringify(function say() {}));// undefined undefined undefined
Copy the code
All properties with symbol as the property key are completely ignored.
const s1 = Symbol(a);const obj6 = { a: 1.b: 2, [s1]: 3 };
console.log(JSON.stringify(obj6)); // {"a":1,"b":2}
Copy the code
Date the Date is converted to a string by calling toJSON() (same as date.toisostring ()), so it is treated as a string.
const obj7 = { a: 1.b: 2.c: new Date() };
console.log(JSON.stringify(obj7)); / / {" a ": 1," b ": 2," c ":" the 2022-02-17 T06: now. 145 z}"
Copy the code
The error object is converted to an empty object.
/ / 5,
const obj8 = { a: 1.b: 2.c: new Error("error")};console.log("Errors are converted to empty objects:".JSON.stringify(obj8)); // {"a":1,"b":2,"c":{}}
Copy the code
The re is converted to an empty object.
const obj9 = { a: 1.b: 2.c: new RegExp("\\d"."i")};console.log("The re is converted to an empty object:".JSON.stringify(obj9)); // {"a":1,"b":2,"c":{}}
Copy the code
Values and nulls in NaN and Infinity formats are treated as null.
const obj10 = { a: 1.b: 2.c: NaN.d: Infinity.e: null };
console.log(JSON.stringify(obj10)); // {"a":1,"b":2,"c":null,"d":null,"e":null}
Copy the code
Executing this method on objects that contain circular references (objects that refer to each other in an infinite loop) throws an error.
// const obj11 = {};
// const obj12 = { a: obj11 };
// obj11.a = obj12;
// console.log(JSON.stringify(obj12));
Copy the code
TypeError is raised when attempting to convert a value of type BigInt (“BigInt value can’t be serialized in JSON”).
// const obj11 = { a: 1, b: 2, c: BigInt("12222222222222222222222") };
// console.log(" Values of type BigInt will raise TypeError: ", json.stringify (obj11));
Copy the code
Well, about JS assignment copy, shallow copy, deep copy, the author has spoken, friends whether understand? Finally, thank you for your patience.
Afterword.
This article is the author’s personal study notes, if there are fallacies, please inform, thank you! If this article helped you, please give it a thumbs up