你知道深浅拷贝分别有哪些方式吗?

·  阅读 10133

嗨!大家好!我是法医,一只治疗系前端码猿🐒,与代码对话,倾听它们心底的呼声,期待着大家的点赞👍与关注➕。

🙉 何为深浅拷贝

  • 浅拷贝:拷贝基本数据类型时,不受任何影响,当拷贝引用类型时,源对象也会被修改。
  • 深拷贝:深拷贝就是完完全全拷贝一份新的对象,它会在内存的堆区域重新开辟空间,修改拷贝对象就不会影响到源对象

🙈 浅拷贝常见方式

  1. 直接赋值
var user1 = {
    name : '法医',
    age : 18
}
var user2 = user1;
user2.name = "前端猎手";
console.log(user1); // { name: '前端猎手', age: 18 }
console.log(user2); // { name: '前端猎手', age: 18 }
复制代码
  1. Object.assign 方法
var user1 = {
    name : "法医"
}
var user2 = Object.assign(user1, {age : 18}, {sex : 'male'});
console.log(user2); // { name: '法医', age: 18, sex: 'male' }
复制代码

这个方法是可以实现拷贝的,但是我们需要注意的是,当属性对应的一个值是引用类型时,我们会发现这也是一个浅拷贝:

var user1 = {
    name: "法医",
    like: {
        eat: "面条",
        sport: "篮球",
        },
   };
             
var user2 = Object.assign({}, user1);
console.log(user1); //{name: '法医', like: {eat: '面条', sport: '篮球'}}
console.log(user2); //{name: '法医', like: {eat: '面条', sport: '篮球'}}
user1.name = "前端猎手";
console.log(user1); //{name: '前端猎手', like: {eat: '面条', sport: '篮球'}}
console.log(user2); //{name: '法医', like: {eat: '面条', sport: '篮球'}}
user1.like.eat = "米饭";
console.log(user1); //{name: '前端猎手', like: {eat: '米饭', sport: '篮//{name: '法医', like: {eat: '面条', sport: '篮球'}}球'}}
console.log(user2); //{name: '法医', like: {eat: '米饭', sport: '篮球'}}
复制代码
  1. ES6 扩展运算符

扩展运算符是 ES6 新提供的语法,它会将可迭代的对象依次展开,使用 ES6 扩展运算符也可以拷贝对象,例如:

var user1 = {
    name: "法医",
    like: {
        eat: "面条",
        sport: "篮球",
        },
   };
             
var user2 = {...user1};
console.log(user1); //{name: '法医', like: {eat: '面条', sport: '篮球'}}
console.log(user2); //{name: '法医', like: {eat: '面条', sport: '篮球'}}
user1.name = "前端猎手";
console.log(user1); //{name: '前端猎手', like: {eat: '面条', sport: '篮球'}}
console.log(user2); //{name: '法医', like: {eat: '面条', sport: '篮球'}}
user1.like.eat = "米饭";
console.log(user1); //{name: '前端猎手', like: {eat: '米饭', sport: '篮//{name: '法医', like: {eat: '面条', sport: '篮球'}}球'}}
console.log(user2); //{name: '法医', like: {eat: '米饭', sport: '篮球'}}
复制代码

通过上面的示例,我们发现 ES6 扩展运算符也是浅拷贝。

  1. 数组的 sliceconcat 方法

上面这两个方法,一个是截取,一个是拼接,这两个方法也可以用于拷贝数组

// 使用 slice 和 concat 方法来拷贝数组
var user1 = ["法医",{eat:"面条",sport:"篮球"}];

var user2 = user1.slice();
var user3 = user1.concat();
console.log(user1);//{name: '法医', like: {eat: '面条', sport: '篮球'}}
console.log(user2);//{name: '法医', like: {eat: '面条', sport: '篮球'}}
console.log(user3);//{name: '法医', like: {eat: '面条', sport: '篮球'}}
user1[0] = "前端猎手";
console.log(user1);//{name: '前端猎手', like: {eat: '面条', sport: '篮球'}}
console.log(user2);//{name: '法医', like: {eat: '面条', sport: '篮球'}}
console.log(user3);//{name: '法医', like: {eat: '面条', sport: '篮球'}}
user1[1].eat = "米饭";
console.log(user1);//{name: '前端猎手', like: {eat: '米饭', sport: '篮球'}}
console.log(user2);//{name: '法医', like: {eat: '米饭', sport: '篮球'}}
console.log(user3);//{name: '法医', like: {eat: '米饭', sport: '篮球'}}
复制代码
  1. jQuery 中的 $.extend

$.extend(deep,target,object1,object2,....) 通过这个方法就可以实现深浅拷贝。各个参数的说明如下:

  • deep:true 表示深拷贝,false 表示浅拷贝
  • target:要拷贝的目标对象
  • object1:待拷贝的对象
 <body>
        <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
        <script>         
            var user = {
                name: "法医",
                age: 18,
                like: {
                    eat: "面条",
                    sport: "篮球",
                },
            };

            var target = {};

            $.extend(target, user);
            target.name = "前端猎手";
            console.log(user); //{name: '前端猎手', like: {eat: '面条', sport: '篮球'}}
            console.log(target); //{name: '前端猎手', like: {eat: '面条', sport: '篮球'}}
        </script>
    </body>
复制代码

🐒 深拷贝

  1. JSON.parse(JSON.stringify(待拷贝对象))

这是一种广为流传的对象深拷贝方式。如下:

var user = {
    name: "法医",
    age: 18,
    like: {
        eat: "面条",
        sport: "篮球",
    },
};

var target = JSON.parse(JSON.stringify(user));
target.like.eat = "米饭";
console.log(user); //{name: '法医', like: {eat: '面条', sport: '篮球'}}
console.log(target); //{name: '法医', like: {eat: '米饭', sport: '篮球'}}
复制代码

但是这种方式有一个缺点,那就是里面的函数无法被拷贝。

var user = {
    name: "法医",
    age: 18,
    like: {
        eat: "面条",
        sport: "篮球",
    },
    say:function(){
        console.log("前端猎手");
    }
};

var target = JSON.parse(JSON.stringify(user));
target.like.eat = "米饭";
console.log(user); //{name: '法医', like: {eat: '面条', sport: '篮球'},say:f()}
console.log(target); //{name: '法医', like: {eat: '米饭', sport: '篮球'}}
复制代码
  1. jQuery 中的 $.extend

上面已经说过了,加上true就可以实现深浅拷贝。

 <body>
        <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
        <script>         
            var user = {
                name: "法医",
                age: 18,
                like: {
                    eat: "面条",
                    sport: "篮球",
                },
            };

            var target = {};

            $.extend(true,target, user);
            target.like.eat = "米饭";
            console.log(user); //{name: '法医', like: {eat: '面条', sport: '篮球'}}
            console.log(target); //{name: '法医', like: {eat: '米饭', sport: '篮球'}}
        </script>
    </body>
复制代码
  1. 手写递归的方式来实现深拷贝
 //origin表示待拷贝对象,target表示目标对象
            function deepClone(origin, target) {
                var target = target || {}, //容错处理,防止用户不传target值
                    toStr = Object.prototype.toString,
                    arrAtr = "[object Array]";
                for (var prop in origin) {
                    //遍历对象
                    if (origin.hasOwnProperty(prop)) {
                        //防止拿到原型链属性
                        if (
                            origin[prop] !== "null" &&
                            typeof origin[prop] == "object"
                        ) {
                            //判断是不是原始值
                            target[prop] =
                                toStr.call(origin[prop]) == arrAtr ? [] : {}; //建立相对应的数组或对象
                            deepClone(origin[prop], target[prop]); //递归,为了拿到引用值里面还有引用值
                        } else {
                            target[prop] = origin[prop]; //是原始值,直接拷贝
                        }
                    }
                }
                return target;
            }
复制代码

😊 好了, 以上就是我的分享,小伙伴们点个赞再走吧 👍 支持一下哦~ 😘,我会更有动力的 🤞

分类:
前端
收藏成功!
已添加到「」, 点击更改