当前位置:网站首页>小白搞一波深拷贝 浅拷贝
小白搞一波深拷贝 浅拷贝
2022-07-26 09:30:00 【豆芽不吃豆】
拷贝:顾名思义就是复制嘛,不过,深浅拷贝之间的差别在于拷贝的第三方数值的改变会不会对原对象产生影响.
浅拷贝
就是新对象复制的是已有对象中非对象属性的值和对象属性的引用,对象属性不会复制到内存
举个例子
obj ={name:‘dress’,{color:‘red’}} newObj浅拷贝obj,复制name的值,当新对象的name发生改变时,原对象(也就是obj)的name不会发生改变;color为对象属性,只会拷贝一份相同的内存地址,新对象中的color值发生改变,原对象中color的值也要改变.
实现浅拷贝的几种方式:
- 对象的浅拷贝:Object.assign(target,…source)
let myobj = {
name:'John',
age:19,
like:"listen",
dislike:'banana',
want:{
pet:"dog"
}
}
let leo = Object.assign({
},myobj);
// 浅拷贝只是在根属性(对象的第一层级)创建了一个新的对象,但对于属性的值是对象的话只会拷贝一份相同的内存地址
leo.name = "Lucy";
console.log(leo.name,myobj.name) // Lucy John 原对象obj的name并没有发生改变
leo.want.pet = 'cat'; //
console.log(leo.want.pet,myobj.want.pet) // cat cat 原对象中的对象属性的值也发生了改变
2.数组的浅拷贝:arr.slice(begin,end):返回一个切割的新数组,原数组不变
let myArr = ['a','d','Ga',{
name:"ad钙"}]
let leoo = myArr.slice.call(myArr);
leoo[0] = "wa";
leoo[1] = "ha";
leoo[2] = 'ha';
leoo[3].name="哇哈哈"
console.log(leoo[0],myArr[0]) // wa a
console.log(leoo,myArr) // ["wa", "ha", "ha", {name: "哇哈哈"}] (4) ["a", "d", "Ga", {name: "哇哈哈"}]
3.实现浅拷贝:Array.prototype.concat():合并>=2个数组,不改变原有数组,返回一个新数组
let myArr = ["a", "d", "Ga", {
name: "哇哈哈"}]
let myArr2 = [{
age:19}]
let leo3 =myArr.concat(myArr2);
leo3[0] = "浅";
leo3[1] = "拷";
leo3[4].age=30;
console.log(leo3,myArr,myArr2) //["浅", "拷", "Ga", {name: "是浅拷贝呀"}, {age: 30}] ["a", "d", "Ga", {name: "是浅拷贝呀"}] [{age: 30}]
4.利用扩展运算符实现浅拷贝: …
let leo4 ={
...myobj};
leo4.age="30";
leo4.want.pet = "panda";
console.log(leo4,myobj)
手写一个浅拷贝:实现原理----新的对象复制已有对象中非对象属性的值和对象属性的引用.对象属性不会复制到内存
function _clone(source) {
let target = {
};
for(let key in source) {
if(Object.prototype.hasOwnProperty.call(source,key)) {
target[key] = source[key]
}
}
return target;
}
let Qcopy = _clone(myobj);
Qcopy.name = "slsk"
Qcopy.want.pet = "cat"
console.log(Qcopy,myobj) //{name: "slsk", age: 19, like: "listen", dislike: "banana", want: {pet: "cat"}}
// {name: "les", age: 19, like: "listen", dislike: "banana", want: {pet: "cat"}}
深拷贝
复制变量值,对于引用数据,则递归至基本类型之后再复制.深拷贝后的对象与原对象完全隔离 互不影响
其实就是深拷贝的时候,系统会单独再给新对象分配一个内存地址,这时深拷贝涉及到的两个对象都拥有各自的内存地址,无论另外一个怎么发生改变,剩下的那个都不会受到任何影响.
实现深拷贝:
1.JSON.parse(JSON.stringfy())—原理:把一个对象序列化为一个JSON字符串,将对象的内容转换成字符串的形式再保存在磁盘上,再用JSON.parse()反序列化将JSON字符串变成一个新的对象
let myobj = {
name:"lmy",
age:18
}
// 实现深拷贝
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
let deepData = deepClone(myobj);
deepData.name = "deep lmy"
console.log(deepData,myobj)
2.使用第三方库,如lodash
手写深拷贝:核心思想是递归,遍历数组,对象,直到里面都是基本数据类型再复制
const isObject = obj => typeof obj === 'object' && obj != null; // 此实现只针对数组与{},由于null的typeof类型也是object,特做过滤
// 只针对{}与数组的简单实现
function cloneDeep(source) {
if(!isObject(source)) {
// 如果参数不是对象{}或数组直接返回
return source;
}
const target = Array.isArray(source) ?[]:{
}; // 创建一个新对象,若传入值为数组,target即为空数组,否则为空对象
for(var key in source) {
// 遍历传入的source,进行拷贝
if(Object.prototype.hasOwnProperty.call(source,key)) {
// 判断是否当前属性是否是自身属性,下面有说明为什么是使用hasOwnProperty.call()
if(isObject(source[key])) {
// 若该属性值是否是对象
target[key] = cloneDeep(source[key]); // 进入递归深拷贝
}else {
target[key] = source[key]
}
}
}
return target
}
// 使用
let sjc = cloneDeep(myobjj);
sjc.name="textsss"
console.log(sjc,myobjj)
简要来说 深浅拷贝的差别就在于看拷贝之后新对象的改变会不会对原对象产生影响,有影响则为浅拷贝.没有为深拷贝.
附上大佬链接:https://mp.weixin.qq.com/s/-fiuJMW_xVaYZxrAuH0TBg 真的写的很详细 强推!!!
--------------------------------------------------------分割线--------------------------------------------------------------------------------------------
hasOwnProperty:判断是否是对象的自有属性
js,存在一些关键字,比如L:undefined/nullif/else/Number/Date…关键字的目的是给这些变量名一些特殊的功能,不能随便使用,起到一种保护作用.在上面深拷贝代码里用到了hasOwnproperty.call()…
原因在于js没有保护hasOwnProperty这个属性名,意思也就是开发者可以占用该属性名称,自定义该属性值
例如:
let objTes = {
name:'hasOwnPropertyText',
hasOwnProperty:function(){
// 也可以是个字符串,数组....自定义使用
return "自定义使用hasOwnProperty"
}
}
console.log(objTes.hasOwnProperty()) // 自定义使用hasOwnProperty
console.log(objTes.hasOwnProperty("name")) // 自定义使用hasOwnProperty
// 在这里占用了hasOwnProperty这个属性名称,所以想要使用hasOwnProperty来判断是否是该对象的自有属性是行不通的
// 需要使用原型链上的hasOwnProperty来判断是否是自有属性,使用为:hasownProperty.call()
Object.prototype.hasOwnProperty.call(objTes,"name") // true
边栏推荐
猜你喜欢
【Flutter -- 布局】Align、Center、Padding 使用详解
Source code analysis of object wait notify notifyAll
csdn空格用什么表示
正则表达式
Under a directory of ext3 file system, subfolders cannot be created, but files can be created
配置ADCS后访问certsrv的问题
Arc GIS basic operation 3
js中树与数组的相互转化(树的子节点若为空隐藏children字段)
cocoapods的安装和使用
Fiddler下载安装
随机推荐
TableviewCell高度自适应
高斯消元求解矩阵的逆(gauss)
js在控制台输出菱形
uni-app学习总结
Order based evaluation index (especially for recommendation system and multi label learning)
TabbarController的封装
使用openLayer画箭头
Local cache
服务器、客户端双认证
多层嵌套后的 Fragment 懒加载实现
模板(三)
青少年软件编程等级考试标准解读_二级
微信小程序图片无法显示时显示默认图片
Windows下Redis哨兵模式搭建
Malloc failed to allocate space and did not return null
Basic use of ArcGIS 1
点击input时,不显示边框!
Qt随手笔记(三)在vs中使用QtCharts画折线图
ZXing简化版,转载
Ext4 file system opens dir_ After nlink feature, link_ Use link after count exceeds 65000_ Count=1 means the quantity is unknown