一、数据类型
js数据类型分为基本数据类型和引用数据类型
基本数据类型(直接存储在栈中的数据):bool,number,string,null,undefined,Symbol
引用数据类型(直接存储在堆内存中的数据):array,object等
保存在栈内存的必须是大小固定的数据,引用类型的大小不固定,只能保存在堆内存中。
二、深拷贝与浅拷贝的理解
深拷贝与浅拷贝均针对于引用数据类型
浅拷贝复制指向某个对象的指针,拷贝的数据会因为原数据的改变而改变;
深拷贝会创造复制一个新的对象与被复制的对象一模一样,不会因为源数据的改变而改变。
三、浅拷贝与赋值的区别
浅拷贝默认拷贝构造函数只是对对象进行浅拷贝复制(逐个成员依次拷贝),即只复制对象空间而不复制资源。
赋值两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容。
四、深拷贝
1.递归拷贝
// 定义一个深拷贝函数 接收目标target参数
function deepClone(target) {
// 定义一个变量
let result;
// 如果当前需要深拷贝的是一个对象的话
if (typeof target === 'object') {
// 如果是一个数组的话
if (Array.isArray(target)) {
result = []; // 将result赋值为一个数组,并且执行遍历
for (let i in target) {
// 递归克隆数组中的每一项
result.push(deepClone(target[i]))
}
// 判断如果当前的值是null的话;直接赋值为null
} else if(target===null) {
result = null;
// 判断如果当前的值是一个RegExp对象的话,直接赋值
} else if(target.constructor===RegExp){
result = target;
}else {
// 否则是普通对象,直接for in循环,递归赋值对象的所有值
result = {};
for (let i in target) {
result[i] = deepClone(target[i]);
}
}
// 如果不是对象的话,就是基本数据类型,那么直接赋值
} else {
result = target;
}
// 返回最终结果
return result;
}
2.JSON.parse(JSON.stringify())
let obj = {name:'前端',data : { name1 : 'vue', name2 : 'react'} };
let obj_json = JSON.parse(JSON.stringify(obj));
console.log(obj === obj_json);
obj.data.name1 = "java";
console.log(obj);//结果为:{name:'前端',data : { name1 : 'java', name2 : 'react'} };
console.log(obj_json);//结果为:{name:'前端',data : { name1 : 'vue', name2 : 'react'} };
五、浅拷贝
1.Object.assign()
let obj = { a: {a: "java", b: "python"} };
let obj_copy = Object.assign({}, obj);
obj_copy.a.a = "js";
console.log(obj.a.a); //js
2.Array.prototype.concat()
let arr = [1, 3, {name: 'java'}];
let arr2=arr.concat();
arr2[2].name= 'js';
console.log(arr);//结果为:[1, 3, {name: 'js'}];
六、误区
使用扩展运算符或循环遍历赋值如果循环拿到基本数据类型赋值即为深拷贝,eg:一维简单数组遍历赋值;若为对象或者复杂数据类型遍历赋值为浅拷贝