Preamble JS base type

  • Basic types: Number, Boolean, String, null, undefined, symbol (ES6 new), BigInt (ES2020)
  • Reference types: Object, Object subtypes (Array, Function)

1. The shallow clone

The clone and the object to be cloned point to the same segment of heap memory. In the following example, OBj and O affect each other

// Shallow clone function
function shallowClone(o) {
  const obj = {};
  for ( let i in o) {
    obj[i] = o[i];
  }
  return obj;
}
// Clone object
const oldObj = {
  a: 1.b: [ 'e'.'f'.'g'].c: { h: { i: 2}}};const newObj = shallowClone(oldObj);
console.log(newObj.c.h, oldObj.c.h); // { i: 2 } { i: 2 }
console.log(oldObj.c.h === newObj.c.h); // true
Copy the code

Use object. assign(target, source) shallow clone

const target = { a: 1.b: 2 }
const source = { b: 4.c: 5 }

const returnedTarget = Object.assign(target, source)

target // { a: 1, b: 4, c: 5 }
returnedTarget // { a: 1, b: 4, c: 5 }
Copy the code

Difference between assignment (=) and shallow copy

    var obj1 = {
        'name' : 'zhangsan'.'age' :  '18'.'language' : [1[2.3], [4.5]],};var obj2 = obj1;// Assign value to


    var obj3 = shallowCopy(obj1);// Shallow copy is obtained
    function shallowCopy(src) {
        var dst = {};
        for (var prop in src) {
            if(src.hasOwnProperty(prop)) { dst[prop] = src[prop]; }}return dst;
    }

    obj2.name = "lisi";
    obj3.age = "20";

    obj2.language[1] = ["二"."Three"];
    obj3.language[2] = ["Four"."Five"];

    console.log(obj1);  
    //obj1 = {
    // 'name' : 'lisi',
    // 'age' : '18',
    // 'language' : [1,[" 三","三"]],
    / /};

    console.log(obj2);
    //obj2 = {
    // 'name' : 'lisi',
    // 'age' : '18',
    // 'language' : [1,[" 三","三"]],
    / /};

    console.log(obj3);
    //obj3 = {
    // 'name' : 'zhangsan',
    // 'age' : '20',
    // 'language' : [1,[" 三","三"]],
    / /};
Copy the code

Shallow copy copies only one layer of the object’s properties, not the reference type of the object’s data.

So when you modify the property age in the shallow copy, you will not modify the original data, but the language property is an array and belongs to the reference type, and the shallow copy will not copy the reference type data.

Basic data types: undefined, Boolean, number, string, null

Reference data types: Object, including Array and function

Deep copy: To copy an object B into an object A, including the child objects in B,

Shallow copy: Copies object B to object A, but does not include child objects in B

2. Deep cloning

JSON parse method

JSON objects The PARSE method deserializes JSON strings into JS objects, and the Stringify method serializes JS objects into JSON strings, and the two methods combine to produce a convenient deep-clone.

JSON. Parse JSON. Stringfy explanation

const newObj = JSON.parse(JSON.stringify(oldObj));
Copy the code
const oldObj = {
  a: 1.b: [ 'e'.'f'.'g'].c: { h: { i: 2}}};// newObj and oldObj are mutually exclusive
const newObj = JSON.parse(JSON.stringify(oldObj));
console.log(newObj.c.h, oldObj.c.h); // { i: 2 } { i: 2 }
console.log(oldObj.c.h === newObj.c.h); // false
newObj.c.h.i = 'change';
console.log(newObj.c.h, oldObj.c.h); // { i: 'change' } { i: 2 }
Copy the code

But it has drawbacks:

  1. Special objects such as functions and regexps cannot be cloned
  2. Object constructor is discarded, with all constructors pointing to Object
  3. Object has a circular reference and an error is reported.

JSON.stringfy

1. Json.stringify ignores the object’s non-traversal property

Enumberable: false The specified property will be ignored

2. The second argument to the json.stringify method

Specifies the attributes that need to be converted to a string.

JSON.stringify({ a:1.b:2},'a'])
// '{"a":1}'
Copy the code

Change the default stringing behavior.

function f(key, value) {
  if (typeof value === "number") {
    value = 2 * value;
  }
  return value;
}

JSON.stringify({ a:1.b:2 }, f)
// '{"a":2,"b":4}'
Copy the code
3. The third argument to the json.stringify method
  • If it is a number, the number of Spaces (up to 10) added before each attribute;
  • If it is a string (no more than 10 characters), the string is appended to the beginning of each line.

The implementation of deep cloning

Base version, regardless of array and loop application etc:

  • If it is an original type, you do not need to continue copying
  • If it is a reference type, create a new object, iterate over the objects to be cloned, and add the properties of the objects to be cloned to the new objects one by one.
function clone(target) {
    if (typeof target === 'object') {
        let cloneTarget = {};
        for (const key in target) {
            cloneTarget[key] = clone(target[key]);
        }
        return cloneTarget;
    } else {
        returntarget; }};Copy the code

Optimized version:

const clone = parent= > {
    const parent = []
    const children = []
    
    const _clone = parent= > {
        if (parent === null) return null;
        if (typeofparent ! = ='object') return parent;
        let child, proto;
        if(isType(parent, 'Array')) {
            // Do special processing for arrays
            child = []
        } else if (isType(parent, 'RegExp')) {
            // Special handling of re objects
            child = new RegExp(parent.source, getRegExp(parent));
            if (parent.lastIndex) child.lastIndex = parent.lastIndex;
        } else if (isType(parent, 'Date')) {
            // Do special processing on the Date object
            child = new Date(parent.getTime());
        } else {
            // Process object types
            proto = Object.getPrototypeOf(parent);
            // Use object.create to break the prototype chain
            child = Object.create(proto)
        }
        // Handle circular references
        const index = parents.indexOf(parent)
        if(index ! = = -1) {
            return children[index]
        }
        parents.push(parent)
        children.push(child)
        
        for (let i in parent) {
            child[i] = _clone(parent[i])
        }
        
        return child;
    }
    return _clone(parent)
}
Copy the code