Detailed description of javascript deep copy (deepClone), javadeepclone
Javascript deep copy is a problem that can be frequently encountered by beginners and even experienced developers. It is not easy to understand the deep copy of javascript.
Deep copy (deepClone )?
Compared with deep copy, it is a small copy. Many beginners are very aggressive when they come into contact with this idea.
Why do I need a deep copy?
In many cases, we need to assign a value to the variable and assign a value to the memory address. However, when assigning a value to the referenced value type, it only shares a memory region, resulting in a value assignment, keep consistent with the previous values.
Let's look at a specific example.
// Assign a var test = {a: 'A', B: 'B'} to test '}; // assign the value of test to test2 // test and test2 share the same memory object, that is, copying var test2 = test; test2.a = 'a2 '; test. a = 'a2 '// true
Illustration:
This makes it easy to understand why the referenced value type data affects each other.
Implementation
To implement a deep copy function, You have to say the value type of javascript.
Determine javascript type
Javascript has the following basic types:
Type description
The undefined type has only one undefined value, which is the value when the variable is not assigned a value.
The null type has only one null value, which is an empty object reference.
Boolean can be set to true or false.
String indicates text information.
Number indicates the Number information.
Object is an unordered set of a series of attributes, including Function functions and Array arrays.
The function and array cannot be determined by using typeof. The Object. prototype. toString method is used here.
[By default, each Object inherits the toString () method from the Object, if this method is not overwritten (masked) by the same name method on the object itself or more similar upper-layer prototype, the toString () of the object is called () the return value is "[object type]". The string type indicates an object type.] [1]
function type(obj) { var toString = Object.prototype.toString; var map = { '[object Boolean]' : 'boolean', '[object Number]' : 'number', '[object String]' : 'string', '[object Function]' : 'function', '[object Array]' : 'array', '[object Date]' : 'date', '[object RegExp]' : 'regExp', '[object Undefined]': 'undefined', '[object Null]' : 'null', '[object Object]' : 'object' }; return map[toString.call(obj)];}
DeepClone
Values of the non-reference value type are directly assigned values, while objects of the reference value type need to be traversed again and assigned recursively.
function deepClone(data) { var t = type(data), o, i, ni; if(t === 'array') { o = []; }else if( t === 'object') { o = {}; }else { return data; } if(t === 'array') { for (i = 0, ni = data.length; i < ni; i++) { o.push(deepClone(data[i])); } return o; }else if( t === 'object') { for( i in data) { o[i] = deepClone(data[i]); } return o; }}
Note that for the function type, the blogger directly assigns a value here or shares a memory value. This is because the function completes some functions and has an input value and a return value. In addition, for upper-layer businesses, it is more about business functions and does not really need to copy functions in depth.
But how do I copy the function type?
The real-time blogger only wants to use new to perform the operation, but the function will execute it again. He cannot imagine what execution results will be! O (random □random) o! There are no other good ideas for the moment. Thank you for your guidance!
At this point, the deep copy is almost complete, and some people feel that it has not been implemented. Why?
Shortest copy?
For a shallow copy, it can be understood as only operating a common memory zone! This may be dangerous! (. ﹏. *)
If you directly operate on the shared data without any control, data exceptions may occur frequently and may be changed by other components. Therefore, you should not directly operate on the data source and encapsulate some methods for the data source to perform CURD operations on the data.
It is almost the same here, but as a front-end, we should not only consider javascript itself, but also consider dom and browsers.
Element type
Let's look at the following code. What will be returned?
Object.prototype.toString.call(document.getElementsByTagName('div')[0])
The answer is [object HTMLDivElement]
Sometimes the dom Element is saved and the deep copy function lacks the judgment on the Element. Instanceof is used to determine the Element. For different tags, tostring returns the constructor corresponding to different tags.
function type(obj) { var toString = Object.prototype.toString; var map = { '[object Boolean]' : 'boolean', '[object Number]' : 'number', '[object String]' : 'string', '[object Function]' : 'function', '[object Array]' : 'array', '[object Date]' : 'date', '[object RegExp]' : 'regExp', '[object Undefined]': 'undefined', '[object Null]' : 'null', '[object Object]' : 'object' }; if(obj instanceof Element) { return 'element'; } return map[toString.call(obj)];}
Other methods?
Jquery implementation
See https://github.com/jquery/jqu...
Underscore implementation
See https://github.com/jashkenas...
Lodash implementation
See https://github.com/lodash/lod...
JSON implementation
Use JSON. stringify first, and then use JSON. parse to implement deep copy. However, the data type only supports the basic numeric type.
Var obj = {a: 'A', B: function () {console. log ('B')} // In JSON. stringify filters out the function. JSON. stringify (obj) // "{" a ":" "}"
Summary
Here we will summarize the deep copy and how to implement a deep copy. In different scenarios, You need to determine whether to use deep copy based on the business scenario.