你知道深浅拷贝分别有哪些方式吗?
嗨!大家好!我是法医,一只治疗系前端码猿🐒,与代码对话,倾听它们心底的呼声,期待着大家的点赞👍与关注➕。
🙉 何为深浅拷贝
- 浅拷贝:拷贝基本数据类型时,不受任何影响,当拷贝引用类型时,源对象也会被修改。
- 深拷贝:深拷贝就是完完全全拷贝一份新的对象,它会在内存的堆区域重新开辟空间,修改拷贝对象就不会影响到源对象
🙈 浅拷贝常见方式
- 直接赋值
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;
}
😊 好了, 以上就是我的分享,小伙伴们点个赞再走吧 👍 支持一下哦~ 😘,我会更有动力的 🤞
转载自:https://juejin.cn/post/7082693702082101278