js简单实现深浅克隆

浅度克隆:原始类型为值传递,引用类型仍为引用传递。改变原对象中的引用类型中的值,后者对象中的值也会被改变。

深度克隆:所有元素或属性均完全复制,与原对象完全脱离,改变原对象中的引用类型中的值,后者对象中的值并不会随其改变。

主要思路浅克隆直接复制第一层中的值,深克隆通过递归来实现

定义函数将其挂载到Object的原型上,函数接收一个参数,用做判断是深克隆还浅克隆,传递参数为true代表深刻隆,传递false或者不传代表浅克隆。然后通过判断其操作的数据类型来实现

  • 如果该数据是funtion类型,直接返回该数据
  • 如果该数据是array类型,遍历数组中的每一项,在根据传递的参数来判断是否深或者浅克隆,如果是深刻隆继续递归调用该函数,在把返回的值放入新数组中,如果是浅克隆,直接将值放入新数组中。
  • 如果该数据是object类型,和数组一样直接遍历其中的值,在判断深浅克隆,最后将数据放入新对象中返回该对象
  • 如果是不是引用数据类型,是基本数据类型就直接返回该值

代码如下

Object.prototype.myReplication = function (deep) {
            //判断该值是类型是否是function,如果是直接返回
            if (typeof this == 'function') {
                return this
            } else if (this instanceof Array) {
                //判断该值是否是是否是数组
                //声明一个新数组
                var newArr = []
                //循环遍历数组中的每一项
                for (let i = 0; i < this.length; i++) {
                    //判断是否要深度克隆,如果要深度克隆递归调用该函数将调用
                    //返回的值添加进新数组,如果不是直接添加进新数组
                    deep ? newArr.push(this[i].myReplication(deep)) : newArr.push(this[i])
                }
                //返回该新数组
                return newArr
            } else if (Object.prototype.toString.call(this) == "[object Object]") {
                //判断其该值是否是一个对象
                //声明一个新对象
                let obj = {}
                //遍历该对象中的每一项的键值对
                for (let j in this) {
                    //判断j是否是对象本身的属性
                    if(this.hasOwnProperty(j)){
                        //判断是否深克隆还是浅克隆,如果是深克隆再次用该值递归调用该函数添加函数返回的值,
                        //如果是浅克隆直接添加该值
                        obj[j] = deep ? this[j].myReplication(deep) : this[j]
                    }
                }
                //最后返回该新对象
                return obj
            } else {
                
                //如果是基本数据类型直接返回,调用其的tostring方法避免在调用函数的过程中
                //被转换成包装类对象
                return this.toString()
            }
        }