JavaScript deep copy (deep clone) Implementation method _javascript skills

Source: Internet
Author: User
Tags extend inheritance shallow copy hasownproperty

In code reuse mode there is a "copy attribute mode" (copying properties pattern). When it comes to code reuse, it's possible to think of the Inheritance of code (inheritance), but it's important to remember the final goal--we need to reuse the code. Inheritance is only a means of implementing code reuse, not the only way. Replication attributes are also a reuse pattern, which differs from inheritance. In this pattern, the object gets a member from another object, and the method is simply to copy it. As is known with jquery, it has a $.extend () method that can be used to replicate attributes in addition to Third-party Plug-ins. Let's look at the implementation code for a extend () function (Note that this is not a jquery source, just a simple example):

function extend (parent, child) {
var i;
If you do not pass in the second parameter child
//Then create a new object child
= Child | | {}; 
Iterate through all the attributes of the parent object//
and filter the attributes on the prototype
//And then copy its properties to the child object for
(i in parent) {
if (parent.hasownproperty) )) {
Child[i] = Parent[i];
}
Returns the target object child returned child
;

The code above is a simple implementation that traverses only the members of the parent object and copies it to the child object. Below we use the above extend () method to test:

var dad = {Name: "Adam"};
var kid = Extend (Dad);

We found that the extend () method was already working properly. But there is a problem, the above gives a so-called shallow copy (shallow clone). When using shallow replication, if you change the properties of a child object, and that property is exactly another object, this action modifies the parent object, which is not the result we want. Consider the following:

var dad = {
counts: [1, 2, 3],
reads: {paper:true}
};
var kid = Extend (Dad)//Call Extend () method copies Dad properties to Kid
(4);//Append 4 to Kid.counts.push array

With the example above, we will find that the dad.counts is also affected by the modification of the kid.counts attribute (adding the element 4). This is because when you use shallow replication, because objects are passed by reference, that is, kid.counts and dad.counts point to the same array (or to the address of the same heap on memory).

Below, let's modify the Extend () function to achieve deep replication. What we need to do is check each attribute of the parent object, and if the property happens to be an object, recursively copy the object's properties. In addition, you need to detect whether the object is an array because the literal creation of the array is different from the literal creation of the object, which is [] and the latter is {}. An array of detections can be detected using the Object.prototype.toString () method, and if it is an array, he will return "[Object array]". Now let's take a look at the Extend () function of the deep copy version:

function Extenddeep (parent, child) {Child
= Child | | {};
for (var i in parent) {
if (Parent.hasownproperty (i)) {
//detect whether the current property is an object
if (typeof parent[i] = = "Object") {
//If the current property is an object, also detect if it is an array
//This is because the literal representation of the arrays and the literal amount of the object represent different//the
former is [] and the latter is {}
child[i] = ( Object.prototype.toString.call (parent[i]) = = = "[Object Array]")? [] : {};
Recursive call extend
extenddeep (Parent[i], child[i]);
} else {
child[i] = parent[i];
}}} return to child;

Well, the deep copy function is already written, so let's test to see if you can expect to do that, that is, a deep copy:

var dad = {
counts: [1, 2, 3],
reads: {paper:true}
};
var kid = extenddeep (dad);
Modify the Counts and reads properties of the Kid
Kid.counts.push (4);
Kid.reads.paper = false;
Console.log (kid.counts); [1, 2, 3, 4]
console.log (kid.reads.paper);//false
Console.log (dad.counts);//[1, 2, 3]

From the example above, we can see that even if the kid.counts and kid.reads of the child objects are modified, the dad.counts and kid.reads of the parent object do not change, so our purpose is achieved.

Here's a summary of the basic ideas for achieving deep replication:

1. Detects whether the current property is an object

2. Because the array is a special object, it is also necessary to detect whether it is an array if the property is an object.

3. If it is an array, create an empty array, otherwise, create a {} empty object and assign the current property to the child object. The Extenddeep function is then called recursively.

The above example allows us to use a recursive algorithm to implement a deep copy method. In fact, the two methods provided by ES5 's new JSON object also allow for deep replication, respectively, Json.stringify () and Json.parse (), which are used to convert objects to strings, while the latter converts strings to objects. Here we use this method to implement a deeply-replicated function:

function Extenddeep (parent, child) {
var i,
proxy;
Proxy = json.stringify (parent); Converts a parent object to
a string proxy = Json.parse (proxy)//Converts a string to an object, which is a copy of parent child
= Child | | {};
For (i in proxy) {
if (Proxy.hasownproperty (i)) {
Child[i] = Proxy[i];
}
}
Proxy = null; Because the proxy is an intermediate object, it can be recycled back to the child
;

Here is the test example:

var dad = {
counts: [1, 2, 3],
reads: {paper:true}
};
var kid = extenddeep (dad);
Modify the Counts and reads properties of the Kid
Kid.counts.push (4);
Kid.reads.paper = false;
Console.log (kid.counts); [1, 2, 3, 4]
console.log (kid.reads.paper);//false
Console.log (dad.counts);//[1, 2, 3]

The test found that it also achieved deep replication. This method is generally recommended, because Json.parse and json.stringify are built-in functions that can be handled more quickly. In addition, the previous method uses recursive calls, and we all know that recursion is a less efficient algorithm.

About JavaScript deep copy (deep clone) Implementation method to introduce you so much, I hope to help you!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.