javascript Focus - Deep Copy and Shallow Copy

Keywords: Javascript Attribute JQuery JSON

I. Deep and shallow copies of arrays

When using JavaScript to manipulate arrays, we often need to backup arrays. It turns out that if we simply assign it to other variables, then we only need to change one of them, and then the others will change, which leads to problems.

Why is that?

Because if it's just a simple assignment, it's just a reference to the address, so changing one will change the other.

var arr = ["One","Two","Three"];

var arrto = arr;
arrto[1] = "test";
document.writeln("The original value of the array:" + arr + "<br />");//Export:The original value of the array: One,test,Three
document.writeln("New values for arrays:" + arrto + "<br />");//Export:New values for arrays: One,test,Three

This is a shallow copy, so how can we not change the original?

Method 1: slice function of js

var arr = ["One","Two","Three"];

var arrtoo = arr.slice(0);
arrtoo[1] = "set Map";
document.writeln("The original value of the array:" + arr + "<br />");//Export:The original value of the array: One,Two,Three
document.writeln("New values for arrays:" + arrtoo + "<br />");//Export:New values for arrays: One,set Map,Three

Method 2: concat method of js

The concat() method is used to connect two or more arrays.

This method does not change the existing array, but only returns a copy of the connected array.

 

var arr = ["One","Two","Three"];

var arrtooo = arr.concat();
arrtooo[1] = "set Map To";
document.writeln("The original value of the array:" + arr + "<br />");//Export:The original value of the array: One,Two,Three
document.writeln("New values for arrays:" + arrtooo + "<br />");//Export:New values for arrays: One,set Map To,Three

 

2. Deep and Shallow Copies of Objects

var a={name:'yy',age:26};
var b=new Object();


b.name=a.name;
b.age=a.age;
a.name='xx';
console.log(b);//Object { name="yy", age=26}
console.log(a);//Object { name="xx", age=26}

perhaps

var deepCopy= function(source) { 

    var result={};

    for (var key in source) {

      result[key] = typeof source[key]==='object'? deepCoyp(source[key]): source[key];

   } 
   return result; 
}

 




object() method: Douglas Crockford, the inventor of json format, proposed an object() function to do this.
function object(o) {

    function F() {}

    F.prototype = o;

    return new F();

  }

//this object()Functions, in fact, only do one thing, that is to put child objects. prototype Attribute, pointing to the parent object, so that the child object and the parent object together.

//When using, the first step is to generate child objects on the basis of parent objects:
var Doctor = object(Chinese);

//Then, add the attributes of the child object itself:
Doctor.career = 'Doctor';
//At this point, the child object has inherited the attributes of the parent object.
alert(Doctor.nation); //China

 

 

Now let's look at Ruan Yifeng's method.

For example, there is now an object called "Chinese".

  var Chinese = {
    nation:'China'
  };

Another object is called a doctor.

  var Doctor ={
    career:'Doctor'
  }

How can I let "doctors" inherit "Chinese people"? That is to say, how can I create a "Chinese doctors" target?

3. Shallow Copies

In addition to using the "prototype chain", there is another way of thinking: to copy all the attributes of the parent object to the child object, can also achieve inheritance.

The following function is to make a copy:

  function extendCopy(p) {

    var c = {};

    for (var i in p) {
      c[i] = p[i];
    }

    c.uber = p;

    return c;
  }

When using, write as follows:

  var Doctor = extendCopy(Chinese);

  Doctor.career = 'Doctor';

  alert(Doctor.nation); // China

But there is a problem with such copies. That is, if the property of the parent object is equal to an array or another object, then in fact, the child object only gets a memory address, not a real copy, so there is the possibility that the parent object will be tampered with.

Look, now add a "birthplace" attribute to Chinese, whose value is an array.

  Chinese.birthPlaces = ['Beijing','Shanghai','Hong Kong'];

Through the extendCopy() function, Doctor inherits Chinese.

  var Doctor = extendCopy(Chinese);

Then we add a city to Doctor's "birthplace":

  Doctor.birthPlaces.push('Xiamen');

What is going on? Chinese's "birthplace" has also been changed!

  alert(Doctor.birthPlaces); //Beijing, Shanghai, Hong Kong, Xiamen

  alert(Chinese.birthPlaces); //Beijing, Shanghai, Hong Kong, Xiamen

So, extendCopy() is just a copy of the basic type of data, which we call "shallow copy". This is how early jQuery implemented inheritance.

IV. Deep Copies

The so-called "deep copy" is to achieve the true sense of the array and object copy. Its implementation is not difficult, as long as the recursive call "shallow copy" on the line.

  function deepCopy(p, c) {

    var c = c || {};

    for (var i in p) {

      if (typeof p[i] === 'object') {

        c[i] = (p[i].constructor === Array) ? [] : {};

        deepCopy(p[i], c[i]);

      } else {

         c[i] = p[i];

      }
    }

    return c;
  }

Write as follows:

  var Doctor = deepCopy(Chinese);

Now, add an attribute to the parent object with an array value. Then, modify this property on the child object:

  Chinese.birthPlaces = ['Beijing','Shanghai','Hong Kong'];

  Doctor.birthPlaces.push('Xiamen');

At this point, the parent object will not be affected.

  alert(Doctor.birthPlaces); //Beijing, Shanghai, Hong Kong, Xiamen

  alert(Chinese.birthPlaces); //Beijing, Shanghai, Hong Kong

Currently, jQuery libraries use this inheritance method.

Posted by hmgroen on Wed, 27 Mar 2019 13:18:29 -0700