Front knowledge

  • The assignment of an object type actually copies the address, resulting in changes to one side and changes to the other
    let a = {
        age: 1
    }
    let b = a
    a.age = 2
    console.log(b.age) / / 2
Copy the code

Shallow copy

  • Object.assign: Copies all property values to the new Object. If the property values are objects, the copy is the address, so it is not a deep copy
    let a = {
        age: 1
    }
    let b = Object.assign({}, a)
    a.age = 2
    console.log(b.age) / / 1
Copy the code
  • By expanding the operator… To implement shallow copy
    let a = {
        age: 1
    }
    letb = {... a} a.age =2
    console.log(b.age) / / 1
Copy the code

Deep copy

  • JSON.parse(JSON.stringify(object))
    • Ignores undefined
    • Ignore the symbol
    • Non-serializable function
    • An error is thrown for objects that cannot resolve a circular reference
    let a = {
    age: 1.jobs: {
            first: 'FE'}}let b = JSON.parse(JSON.stringify(a))
    a.jobs.first = 'native'
    console.log(b.jobs.first) // FE

    let a = {
        age: undefined.sex: Symbol('male'),
        jobs: function() {},
        name: 'yck'
    }
    let b = JSON.parse(JSON.stringify(a))
    console.log(b) // {name: "yck"}
Copy the code
  • recursive
    function isObject(obj) {
        / / Object. The prototype. ToString. Call (obj) = = = '[Object Object]' keep array form, used here is not suitable
        return typeof obj === 'object'&& obj ! =null
    }

    function cloneDeep1(obj){
        if(! isObject(obj))return obj
        var newObj = Array.isArray(obj)? [] : {}
        for (var key in obj) {
            if (obj.hasOwnProperty(key)) {
                newObj[key] = isObject(obj[key])? cloneDeep1(obj[key]) : obj[key]
            }
        }
        return newObj
    }
Copy the code
  • The problem: The biggest problem with recursive methods is stack bursting, which occurs when the data level is very deep, such as circular references

    var a = {
        name: "muyiy".a1: undefined.a2: null.a3: 123.book: {title: "You Don't Know JS".price: "45"}
    }
    a.circleRef = a
    
    // TypeError: Converting circular structure to JSON
    JSON.parse(JSON.stringify(a))

    //Uncaught RangeError: Maximum call stack size exceeded at Object.hasOwnProperty (<anonymous>)
    cloneDeep1(a)

Copy the code
  • Solution: cyclic detection (set up an array or hash table to store the copied object, when the detection of the current object already exists in the hash table, fetch the value and return can be)
/ / a hash table
function cloneDeep3(source, hash = new WeakMap(a)) {

    if(! isObject(source))return source; 
    if (hash.has(source)) return hash.get(source); // add code to check hash table
      
    var target = Array.isArray(source) ? [] : {};
    hash.set(source, target); // Add code, hash table set value
    
    for(var key in source) {
        if (Object.prototype.hasOwnProperty.call(source, key)) {
            if (isObject(source[key])) {
                target[key] = cloneDeep3(source[key], hash); // Add code to pass in hash table
            } else{ target[key] = source[key]; }}}return target;
}

/ / array
function cloneDeep3(source, uniqueList) {

    if(! isObject(source))return source; 
    if(! uniqueList) uniqueList = [];// Add code to initialize the array
      
    var target = Array.isArray(source) ? [] : {};
    
    // Data already exists, return saved data
    var uniqueData = find(uniqueList, source);
    if (uniqueData) {
        return uniqueData.target;
    };
        
    // Data does not exist, save the source data, and the corresponding reference
    uniqueList.push({
        source: source,
        target: target
    });

    for(var key in source) {
        if (Object.prototype.hasOwnProperty.call(source, key)) {
            if (isObject(source[key])) {
                target[key] = cloneDeep3(source[key], uniqueList); // Add code to the array
            } else{ target[key] = source[key]; }}}return target;
}

// Add a method for finding
function find(arr, item) {
    for(var i = 0; i < arr.length; i++) {
        if (arr[i].source === item) {
            returnarr[i]; }}return null;
}

Copy the code