1、数据类型
数据分为基本数据类型(String, Number, Boolean, Null, Undefined,Symbol)和对象数据类型。
基本数据类型的特点:直接存储在栈(stack)中的数据
引用数据类型的特点:存储的是该对象在栈中引用,真实的数据存放在堆内存里
引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。
2、深浅拷贝的区别
深浅拷贝主要区别在复杂数据类型,对于基本数据类型,没有区别,改变拷贝的数据,都不会改变原数据
浅拷贝(shallow copy):
浅拷贝只拷贝引用(地址值),当拷贝的新对象发生改变时,原对象也会发生相同的改变,也就是说,浅拷贝会影响原来的元素
深拷贝(deep copy):
每一级的数据都会拷贝,拷贝后,两个对象拥有不同的地址,当拷贝出来的对象发生改变时,原对象内容不会改变,两者互不影响
3、实现浅拷贝
(1)、直接赋值法:
var arr = [1,2,3]
var newarr = arr;
newarr[1] = 5;
console.log(arr,newarr);//[1, 5, 3],[1, 5, 3]
(2)、Object.assign()
Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是 Object.assign()进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。
<script>
// 1.Object.assign()
var obj = {
name: "jack",
age: 18,
person: {
name: "tim",
age: 28,
},
};
//将{}和obj合并,返回一个新的obj对象
var objNew = Object.assign({}, obj);
objNew.name = "tom";//当object只有一层的时候,是深拷贝
objNew.person.name = "Diana";//当object只有一层的时候,是浅拷贝
console.log(obj, "obj");
console.log(objNew, "objNew");
</script>
(3)、Array.prototype.concat()
数组的concat方法 用途: 合并2个或多个数组,返回一个浅拷贝对象
<script>
//3、Array.prototype.concat()
var arr2 = [1, "hello", { usename: "tom" }];
var arr3 = arr2.concat();
arr2[2].usename = "tim";
console.log(arr2[2].usename, "arr2"); //tim
console.log(arr3[2].usename, "arr3"); //tim
</script>
(4)Array.prototype.slice()
slice(start, end); start为起始元素位置,end为截止元素位置,
var arr4 = [1, "hello", { usename: "tom" }];
var arr5 = arr4.slice();
arr4[2].usename = "diana";
//console.log(arr4[2].usename, "arr4"); //diana
//console.log(arr5[2].usename, "arr5"); //diana
深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的。
对于字符串、数字及布尔值来说(不是 String、Number 或者 Boolean 对象),slice 会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。
4、实现深拷贝
(1)、Object.assign()
当对象中只有一级属性,没有二级属性的时候,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性以后就是浅拷贝。
<script>
//1、Object.assign();
var obj = {
//当object只有一层的时候,是深拷贝
name: "jack",
age: 18,
};
var objNew = Object.assign({}, obj);
objNew.name = "tom";
console.log(obj.name, "obj"); //jack
console.log(objNew.name, "objNew"); //tom
</script>
(2)、JSON.parse(JSON.stringify())
原理:用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝
注意:这种方法虽然可以实现数组或对象深拷贝,但不能处理函数
<script>
var arr1 = [
1,
"hello",
{ usename: "tom" },
function () {
console.log(111);
},
];
var arr2 = JSON.parse(JSON.stringify(arr1));
arr1[2].usename = "diana";
console.log(arr1[2].usename); //diana
console.log(arr2[2].usename); //tom
console.log(arr2[3]);//null
</script>
(3)、手写递归方法
原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝
<script>
function deepClone(oldData) {
// 1、判断oldData的数据类型
if (typeof oldData == "object" && oldData !== null) {
// 3、再判断类型是否是数组,根据类型返回[],{},开辟新的空间,放深拷贝数据
var res = Array.isArray(oldData) ? [] : {};
// 4、遍历数据,拿到属性,将属性值赋值给拷贝的数据
for (var k in oldData) {
// 5、判断这个k属性是否是oldData上自有的属性,原型链上的就不算了
if (oldData.hasOwnProperty(k)) {
// 6、对象有可能是嵌套对象,所以,需要递归再进行判断,一层层,直到拷贝了所有的数据
res[k] = deepClone(oldData[k]);
}
}
return res;
} else {
// 2、如果不是对象或数组,则返回原数据
return oldData;
}
}
// 测试:
let obj = {
name: "jack",
age: 18,
hobby: ["song", "run"],
sayHi(msg) {
console.log(msg);
},
};
let newObj = deepClone(obj);
// obj.sayHi("hi");
// newObj.sayHi("hello");
newObj.name = "tom";
newObj.hobby = ["唱歌", "跑步"];
console.log(obj, "obj");
console.log(newObj, "newObj");
</script>
(4)、通过jQuery的extend方法实现深拷贝
var array = [1,2,3,4];
var newArray = $.extend(true,[],array);
(5)、lodash函数库实现深拷贝
lodash很热门的函数库,提供了 lodash.cloneDeep()实现深拷贝
1822

被折叠的 条评论
为什么被折叠?



