One , data type
Data is divided into basic data types (String, Number, Boolean, Null, Undefined,Symbol(new in ES 6) and
Reference data type ( Collectively referred to as Object type , In terms of segmentation, there are :Object ,Array ,Date ,RegExp,Function… ).
*
Characteristics of basic data types : Store directly on the stack (stack) Data in
* Characteristics of reference data types : The object is stored in the stack reference , The real data is stored in heap memory
The reference data type stores a pointer in the stack , The pointer points to the starting address of the entity in the heap . When the interpreter looks for a reference value , Its address in the stack is retrieved first , Get the address and get the entity from the heap .
Two , Shallow copy and deep copy
Deep copy and shallow copy are only for Object and Array Such a reference data type .
The schematic diagram of shallow copy and deep copy is as follows :
Shallow copy copies only the pointer to an object, not the object itself , The old and new objects still share the same memory .
But deep copy creates as like as two peas. , The new object does not share memory with the original object , Modifying a new object does not change to the original object .
Three , The difference between assignment and shallow copy
* When we assign an object to a new variable , The assignment is actually the address of the object in the stack , Instead of data in the heap
. 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 .
* A shallow copy is a bitwise copy of an object , It creates a new object
, This object has an exact copy of the property values of the original object . If the property is a base type , What you copy is the value of the base type ; If the property is a memory address ( reference type ), The copy is the memory address
, So if one of the objects changes the address , It affects another object . Namely : The default copy constructor only makes shallow copy copies of objects ( Copy one member at a time ), That is, only the object space is copied, not the resources .
Let's start with two examples , What changes will be made to the original object by comparing assignment with shallow copy ?
Object Assignment :
var obj1 = {
'name' : 'zhangsan',
'age' : '18',
'language' : [1,[2,3],[4,5]],
};
var obj2 = obj1;
obj2.name = "lisi";
obj2.language[1] = [" Two "," Three "];
console.log('obj1',obj1)
console.log('obj2',obj2)
Light copy :
var obj1 = {
'name' : 'zhangsan',
'age' : '18',
'language' : [1,[2,3],[4,5]], //Array
};
var obj3 = shallowCopy(obj1);
obj3.name = "lisi";
obj3.language[1] = [" Two "," Three "];
function shallowCopy(src) {
var dst = {};
for (var prop in src) {
if (src.hasOwnProperty(prop)) {
dst[prop] = src[prop];
}
}
return dst;
}
console.log('obj1',obj1)
console.log('obj3',obj3)
In the example above ,obj1 It's raw data ,obj2 It is obtained by the assignment operation , and obj3 Shallow copy . We can clearly see the impact on the raw data , Please see the table below for details :
Four , Implementation of shallow copy
1.Object.assign()
Object.assign() Method can copy the enumerable properties of any number of source objects to the target objects , It then returns the target object . however
Object.assign() It's a shallow copy , What is copied is a reference to an object's properties , Not the object itself .
var obj = { a: {a: "kobe", b: 39} };
var initalObj = Object.assign({}, obj);
initalObj.a.a = "wade";
console.log(obj.a.a); //wade
be careful : When object When there's only one floor , It's a deep copy
let obj = {
username: 'kobe'
};
let obj2 = Object.assign({},obj);
obj2.username = 'wade';
console.log(obj);//{username: "kobe"}
2.Array.prototype.concat()
let arr = [1, 3, {
username: 'kobe'
}];
let arr2=arr.concat();
arr2[2].username = 'wade';
console.log(arr);
Modifying the new object will change to the original object :
3.Array.prototype.slice()
let arr = [1, 3, {
username: ' kobe'
}];
let arr3 = arr.slice();
arr3[2].username = 'wade'
console.log(arr);
Similarly, modifying the new object will change to the original object :
about Array Of slice and concat Supplementary explanation of the method :
Array Of slice and concat Method does not modify the original array , Only a new array with shallow copies of the elements in the original array is returned .
The elements of the original array are copied according to the following rules :
* If the element is an object reference ( Not the actual object ),slice
This object will be copied to the new array . Both object references refer to the same object . If the referenced object changes , The element in the new and original arrays will also change .
* For Strings , Numbers and Boolean values ( no String,Number perhaps Boolean object ),slice
The values are copied to the new array . Modify these strings or numbers or boolean values in other arrays , Another array will not be affected .
Maybe this paragraph is obscure , Let's take an example , Modify the example above :
let arr = [1, 3, {
username: ' kobe'
}];
let arr3 = arr.slice();
arr3[1] = 2
console.log(arr,arr3);
Five , Implementation of deep copy
1.JSON.parse(JSON.stringify())
let arr = [1, 3, {
username: ' kobe'
}];
let arr4 = JSON.parse(JSON.stringify(arr));
arr4[2].username = 'duncan';
console.log(arr, arr4)
principle :
use JSON.stringify Convert object to JSON character string , Reuse JSON.parse() Parse a string into an object , As soon as we go , New objects are created , And objects will open up new stacks , Realize deep copy .
This method can realize deep copy of arrays or objects , But you can't handle functions
let arr = [1, 3, {
username: ' kobe'
},function(){}];
let arr4 = JSON.parse(JSON.stringify(arr));
arr4[2].username = 'duncan';
console.log(arr, arr4)
that is because JSON.stringify() The method is to add a JavaScript value ( Object or array ) Convert to a JSON character string , Cannot accept function
2. Handwriting recursion method
The principle of deep cloning by recursion : Traversing objects , Arrays up to the inside are primitive data types , And then copy it , It's deep copy
// Define the function of detecting data type
function checkedType(target) {
return Object.prototype.toString.call(target).slice(8, -1)
}
// Realize deep cloning --- object / array
function clone(target) {
// Determine the data type of the copy
// initialize variable result Data that becomes the final clone
let result, targetType = checkedType(target)
if (targetType === 'object') {
result = {}
} else if (targetType === 'Array') {
result = []
} else {
return target
}
// Traverse target data
for (let i in target) {
// Get each item value of traversal data structure .
let value = target[i]
// Whether there is a target value in each object / array
if (checkedType(value) === 'Object' ||
checkedType(value) === 'Array') { // object / Objects are nested in the array / array
// Continue traversing to get value value
result[i] = clone(value)
} else { // Get to value Values are basic data types or functions .
result[i] = value;
}
}
return result
}
3. function library lodash
The library is also available _.cloneDeep used to Deep Copy
var _ = require('lodash');
var obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3]
};
var obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);
// false
Technology