一、数据类型:
基本数据类型:string、number、boolean、null、undefined
引用数据类型:Object、Array、Function
基本数据类型的特点:直接把值存储在栈中的数据;
引用数据类型的特点:栈中存储的是引用(地址),真正的对象是保存在堆内存里面的。
二、深拷贝和浅拷贝:
深拷贝和浅拷贝主要是针对引用数据类型。
如图所示:
浅拷贝:

深拷贝:

浅拷贝只复制指向某个对象的指针,而不复制对象本身,两个变量指向同一块内存空间。但是深拷贝会另外创建一个一模一样的对象,新旧对象不共享内存,对其中一个对象的修改不会影响另一个对象。
三、浅拷贝的实现方式:
1、直接把用用数据赋值给一个变量
let obj = {
name:'kimi',
age:'26'
};
let obj1 = obj;
obj.name = 'haha';
console.log(obj);
console.log(obj1);
2、Object.assign()
let obj = {
name:'kimi',
age:'26'
};
let obj1 = Object.assign(obj);
obj.name = 'hehe';
console.log(obj);
console.log(obj1);
3、Array.prototype.concat()
let arr = [1,2,{
name:'kimi'
}];
let arr1 = arr.concat();
arr1[2].name = 'jinjin';
console.log(arr);
console.log(arr1);
4、Array.prototype.slice()
let arr = [1,2,{
name:'kimi'
}];
let arr1 = arr.slice();
arr1[2].name = 'mimi';
console.log(arr);
console.log(arr1);
深入理解数组的slice()和concat()方法
Array的slice和concat方法不修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。
原数组的元素会按照下述规则拷贝:
- 如果该元素是个对象引用(不是实际的对象),slice 会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变。
- 对于字符串、数字及布尔值来说(不是 String、Number 或者 Boolean 对象),slice 会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。
例:
let arr = [1,2,{
name:'kimi'
}];
let arr1 = arr.slice();
arr1[1] = 3;
console.log(arr);
console.log(arr1);
原数组arr中基本数据类型不受影响。
四、深拷贝的实现
1、JSON.parse(JSON.stringify())
let arr = [1,2,{
name:'kimi'
}];
let arr1 = JSON.parse(JSON.stringify(arr));
arr1[2].name = "jinjin";
console.log(arr);
console.log(arr1);
JSON.stringify()将对象转成字符串,此时进行的是值的复制,然后再将字符串准换成对象,这样产生的新对象,开辟了新的内存空间,实现了深拷贝。
存在问题:
(1)这种方法虽然可以实现数组或对象深拷贝,但不能处理函数;
例:
let arr = [1,2,{
name:'kimi'
},function(){}];
let arr1 = JSON.parse(JSON.stringify(arr));
arr1[2].name = "jinjin";
console.log(arr);
console.log(arr1);

这是因为JSON.stringify() 方法是将一个JavaScript值(对象或者数组)转换为一个 JSON字符串,不能接受函数。
2、递归实现深拷贝
function deepCopy(obj){
var res = Array.isArray(obj)?[]:{};
if(obj && typeof obj === 'object'){
for(var key in obj){
if(obj.hasOwnProperty(key)){
if(obj[key] && typeof obj[key] === 'object'){
res[key] = deepCopy(obj[key]); //注意要有返回值
}else{
res[key] = obj[key];
}
}
}
}
return res;
}
var obj = {
name:'kimi',
age:26,
friend:['jinjin'],
sayName:function(){
console.log(this.name);
}
};
var res = deepCopy(obj);
console.log(obj);
console.log(res);
note:循环引用
var obj = {
a:1,
b:obj
};
var res = deepCopy(obj);
console.log(obj);
console.log(res);
3、函数库lodash
该函数库也有提供_.cloneDeep用来做 Deep Copy

该方法可以解决循环引用、存在函数、和undefined这三种情况的深拷贝。