浅拷贝常见方式

直接赋值
var user1 = {
name : ‘法医’,
age : 18
}
var user2 = user1;
user2.name = “前端猎手”;
console.log(user1); // { name: ‘前端猎手’, age: 18 }
console.log(user2); // { name: ‘前端猎手’, age: 18 }
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: ‘篮球’}}
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 扩展运算符也是浅拷贝。

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

// 使用 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: ‘篮球’}}
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>

🐒 深拷贝
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: '篮球'}}

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>

手写递归的方式来实现深拷贝

//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;
            }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

故事只若初见

坚持就是胜利

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值