深拷贝和浅拷贝的区别是什么?实现一个深拷贝(前端面试)

深拷贝和浅拷贝的区别是什么?如何实现一个深拷贝(前端面试)

深拷贝浅拷贝是针对复杂类型来说的,浅拷贝只拷贝一层,而深拷贝是层层拷贝

深拷贝

深拷贝复制变量值,对于非基本类型的变量,则递归至基本类型的变量后,在复制。

深拷贝的对象与原来的对象时完全隔离的,互不影响,对一个对象的修改并不会影响另一个对象。

浅拷贝

浅拷贝是将对象的每个属性进行依次复制,但是当对象的属性是引用类型时,实质复制的是其引用,当引用对象指向的值改变时也会跟着变化

实现

可以使用 forinObject.assign、扩展运算符...Array.prototype.slice()Array.prototype.concat()等,例如:

let obj = {
    name: 'hz',
    age: '18',
    hobbies: ['reading', 'photography', 'music']
}
let obj2 = Object.assign({}, obj)
let obj3 = {...obj}

obj.name = 'wBekvam'
obj.hobbies.push('coding')
console.log(obj)
//{ name: 'wBekvam', age: '18', hobbies: [ 'reading', 'photography', 'music', 'coding' ]}
console.log(obj2)
//{ name: 'hz', age: '18', hobbies: [ 'reading', 'photography', 'music', 'coding' ]}
console.log(obj3)
//{name: 'hz', age: '18', hobbies: [ 'reading', 'photography', 'music', 'coding' ]}

可以看出浅拷贝只对第一层属性进行了拷贝,当第一层的属性值是基本数据类型时,新的对象和原对象互不影响,但是如果第一层的属性值是复杂数据类型,那么新对象和原对象的属性值其指向的是同一块内存地址。

深拷贝实现

  1. 深拷贝最简单的实现是:JSON.parse(JSON.stringify(obj))

JSON.parse(JSON.stringify(obj))是最简单的实现方式,但是有些缺陷:

  1. 对象的属性值是函数时,无法拷贝
  2. 原型链上的属性无法拷贝
  3. 不能正确处理 Date 类型的数据
  4. 不能处理 RegExp (正则)
  5. 会忽略 symbol
  6. 会忽略undefined
  1. 实现一个 deepClone 函数
  1. 如果时基本数据类型,直接返回

  2. 如果时 RegExp 或则 Date 类型,返回对应类型

  3. 如果复杂数据类型,递归

  4. 考虑循环引用的问题

    // 递归拷贝
    function deepClone(obj, hash = new WeakMap()) { 
        if (obj instanceof RegExp) return new RegExp(obj)
        if (obj instanceof Date) return new Date(obj)
        if (obj === nul || typeof obj !== 'object') {
            // 不是复杂类型,直接返回
            return obj
        }
        if (hash.has(obj)) {
            return hash.get(obj)
        }
        /**
         * 如果obj是数组,那么 obj.construtor 是 [Function: Array]
         * 如果obj是对象,那么 obj.construtor 是 [Function: Object]
         */
        let t = new obj.construtor()
        hash.set(obj, t)
        for (let key in obj) {
            // 递归
            if (obj.hasOwnProperty(key)) { //是否是自身的属性
                t[key] = deepClone(obj[key], hash)
            }
        }
        return t
    }
    

3. 使用 Object.create() 方法实现深拷贝

function deepClone(initalObj, finalObj) {    
  var obj = finalObj || {};    
  for (var i in initalObj) {  
    // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
    var prop = initalObj[i];        
    if(prop === obj) {            
      continue;
    }        
    if (typeof prop === 'object') {
      obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);
    } else {
      obj[i] = prop;
    }
  }    
  return obj;
}

你可能感兴趣的:(JavaScript,面试)