在JavaScript数据类型可以分为8中:字符串(String
)、数字 (Number
)、布尔 (Boolean
)、空(Null
)、未定义(Undefined
)、Symbol 、Object、BigInt
(任意大的整数)
也可以分为基本数据类型、引用数据类型。
基本数据类型:字符串(String
)、数字 (Number
)、布尔 (Boolean
)、空(Null
)、未定义(Undefined
)、Symbol
-----------存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配。
引用数据类型:Object
【Object是个大类,function函数、array数组、date日期...等都归属于Object】
-----------存放在堆内存中的对象,在栈内存中存的是一个指针,这个指针指向堆内存一个位置。再从堆内存中取得所需的数据。
区别:
深拷贝:在堆内存中重新开辟一个存储空间,完全克隆一个一模一样的对象。
浅拷贝:不在堆内存中重新开辟空间,只复制栈内存中的引用地址。
本质上两个对象(数组)依然指向同一块存储空间。赋值引用类型的时候肯定不能出现浅拷贝的现象,会对原数据产生影响,那么就要进行深拷贝。
常用的深拷贝方式:
1.JSON.stringify():可以深拷贝的数组和对象,但是不能拷贝undefined和Function类型数据,序列化之后会直接丢失。
var arr = {
name: 'lemon1号',
age: 23,
foods: ['冰淇淋', '水蜜桃'],
friend: {
name: '张三',
age: '22'
},
function(){
console.log("lemon1号的对象")
}
}
//先转为json格式字符,再转回来
var _arr=JSON.parse(JSON.stringify(arr))
_arr.name='lemon2号'
_arr.adress[0]='大西瓜'
console.log("arr为", arr)
console.log("_arr为", _arr)
2. 封装一个递归方法:这是最保险最推荐的写法。多数第三方库lodash中的cloneDeep()方法底层也是基于的递归。
//使用递归实现深拷贝
function deepClone(obj) {
//变量先置空
let newobj = null;
//obj不能为空,并且是对象或者是数组,null也是object
if (typeof (obj) == 'object' && obj !== null) {
newobj = obj instanceof Array ? [] : {};
//递归进行深度的拷贝
for (var i in obj) {
newobj[i] = deepClone(obj[i])
}
//如果不是对象直接赋值
} else {
newobj = obj;
}
return newobj;
}
//------------------- 使用 ----------------------
let obj = {
name: 'lemon1号',
age: null,
foods: ['冰淇淋', '水蜜桃'],
friend: {
name: '张三',
age: '22'
},
function(){
console.log("lemon1号的对象")
}
}
const newObj = deepClone(obj); //这样就完成了一个对象的递归拷贝
newObj.name = 'lemon2号';
console.log(newObj);
3.使用扩展运算符:利用了对象的结构赋值特性方法,只能对第一层引用对象进行深拷贝,对于对象中的对象则失效。
var arr = {
name: 'lemon1号',
age: undefined,
foods: ['冰淇淋', '水蜜桃'],
friend: {
name: '张三',
age: '22'
},
function(){
console.log("lemon1号的对象")
}
}
var _arr={...arr} //这样就完成了一个对象一级拷贝
_arr.name='lemon2号'
_arr.friend.name='赵四'
_arr.foods[0]='大西瓜'
console.log("arr为", arr)
console.log("_arr为", _arr)
4.JQuery的extend()方法进行深拷贝:在JQuery构建的项目中,JQuery自身携带的extend()方法可以进行深拷贝。但是对于undefined类型数据,extend()方法之后会直接丢失。两拷贝对象中有相同的属性名时,后者的值也会覆盖前者的值。
var obj = {
name: 'lemon1号',
age: undefined,
foods: ['冰淇淋', '水蜜桃'],
friend: {
name: '张三',
age: '22'
},
function(){
console.log("lemon1号的对象")
}
}
let _obj= $.extend(true, {}, obj); //这样就完成了一个对象一级拷贝
_obj.name='lemon2号'
_obj.friend.name='赵四'
_obj.foods[0]='大西瓜'
console.log("obj为", obj)
console.log("_obj为", _obj)
总结:在JQuery项目中推荐使用extend()函数,其他项目推荐使用封装的递归函数。