深度拷贝(克隆)

首先明确的一点是“赋值”语句不是拷贝(克隆),但是“赋值语句”属于“浅拷贝”,浅拷贝意味着修改一个Object对象({})或者是一个Array(数组对象)时,另外的一个对应的Object对象({})或者是一个Array(数组对象)也会发生相应的改变

下面的代码其实达不到深拷贝的目的,因为,区别是深拷贝还是浅拷贝关键点要通过最开始的数据类型中的数据的类型是引用地址才可以达到判断的目的,举个例子,深浅拷贝是看下面Arr的内容的数据类型,arr = [1, 2,[], {}],也就是在拷贝数据的时候,arr中的[]和{}的是以地址的形式拷贝过去的,还是只是指拷贝[]和{}中的基本数据类型过去的

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>深度克隆(拷贝)实现</title>
    <script>
        window.onload = function(){
            // 创建获取类型的方法
            function getType(target){
                return Object.prototype.toString.call(target)
            }

            // 创建克隆的方法
            function cloneUtil(target){
                // 根据target类型构造最外层具体的数据类型
                let result
                if(getType(target)==="Object"){
                    result = {}
                }else if(getType(target)==="Array"){
                    result = []
                }else result = target

                // 通过for...in....实现遍历
                for(let i in target){//这里使用的是for...in...,而没有使用forEach和for...of...,是为了统一使用
                    // 提取出每一个具体的值:属性值或者是数组的数据
                    result[i] = target[i] //给Object对象或者是Array对象拷贝内容
                }

                return result
            }


            let obj1 = {
                name: "张三",
                age: 18,
                sayName(){
                    console.log(this)
                }
            }

            let obj2 = cloneUtil(obj1)
            obj1.sayName = "王五"
            console.log(obj2)
            console.log(obj1)
        }
    </script>
</head>
<body>
    
</body>
</html>

在这里插入图片描述

完整版的深度克隆如下所示

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>深度克隆(拷贝)实现</title>
    <script>
        window.onload = function(){
            // 创建获取类型的方法
            function getType(target){
                return Object.prototype.toString.call(target).slice(8, -1)
            }

            // 创建克隆的方法
            function cloneUtil(target){
                // 根据target类型构造最外层具体的数据类型
                let result
                if(getType(target) ==="Object"){
                    console.log("------------")
                    result = {}
                }else if(getType(target)==="Array"){
                    result = []
                }else result = target

                // 通过for...in....实现遍历
                for(let i in target){//这里使用的是for...in...,而没有使用forEach和for...of...,是为了统一使用
                    // 提取出每一个具体的值:属性值或者是数组的数据

                    // 判断要拷贝的值是引用地址还是基本数据类型
                    let item = target[i]
                    // console.log(getType(item) === "Object")
                    if(getType(item) === "Object" || getType(item) === "Array"){
                        result[i] = cloneUtil(item) //这里其实是一个递归调用,而且,这里的result[i]不能去掉的
                    }else{
                        result[i] =  item //给Object对象或者是Array对象拷贝内容
                    }
                }
                return result 
            }


            let obj1 = {
                name: "张三",
                age: 18,
                sayName: {
                    option:"男"
                }
            }

            let obj2 = cloneUtil(obj1)
            obj1.sayName.option= "王五"
            console.log(obj2)
            console.log(obj1)
        }
    </script>
</head>
<body>
    
</body>
</html>

在这里插入图片描述

深度克隆的关键在于,当Object对象或者是Array数据中含有引用数据类型(指定是数组array([])和Object({})),此时在深度克隆时,此处会创建一个新的

在这里插入图片描述
而不是,第一个代码中的直接是把原来的旧地址给赋值过去
在这里插入图片描述

深度拷贝的思想

在这里插入图片描述

特别注意的是,基本数据类型以及function没有深度拷贝的说法,也就是深度拷贝只和Object({})对象和Array([])有关,更准确地说,不关注Object({})对象和Array([])本身,而是它里面的数据类型是否含有Object({})对象和Array([])的引用地址

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值