前言

1,基本数据类型:Number,String,Undefined,Null,Boolean,Symbol,BigInt(ES10的新特性,比2^53大的数可以使用BigInt类型表示)

引用数据类型:object(Array,function,date,RegExp)

2,栈:为自动分配的内存空间,它由系统自动释放。

堆:为动态分配内存空间,大小不定,不会自动释放。

基本数据类型都是保存在栈当中。

引用类型都是保存在堆当中的,引用类型的值都是对象,保存在堆内存,而栈当中存储的是对象的标识符以及对象在堆内存中的存储地址。

一、赋值

赋值就是将某一数值或对象赋给某个变量的过程,分为:

1,基本数据类型:赋值,赋值之后两个变量互不影响。

1
2
3
4
5
let a = "123";
let b = a;
b = "456"
console.log(a); // 123
console.log(b); // 456

2,引用数据类型:赋值,两个变量具有相同,指向同一个引用对象,互相之间有影响。

1
2
3
4
5
6
7
let obj = {
a: "123"
}
let objCopy = obj;
objCopy.a = "456";
console.log(obj.a); //456
console.log(objCopy.a); //456

二、浅拷贝

浅拷贝的时候如果数据是基本数据类型,那么就如同直接赋值那种,会拷贝其本身,如果除了基本类型之外还有一层对象,那么对于浅拷贝而言就只能拷贝其引用,对象的改变会应到拷贝对象身上。

1,直接复制

1
2
3
4
5
6
7
8
9
10
11
12
var obj = {
name:123,
list:[1,2,3,4,5],
fn(){
alert(this.name)
},
};
var obj2 = obj;
obj2.name = 456;
obj2.list.push(6,7,8);
console.log(obj2.name,obj.name) //456,456
console.log(obj2.list,obj.list) //[1,2,3,4,5,6,7,8],[1,2,3,4,5,6,7,8]

2,for…in

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var obj = {
name:123,
list:[1,2,3,4,5],
fn(){
alert(this.name)
},
info:{
title:'标题',
subtitle:'副标题'
}
};
var obj2 = {};
for(let x in obj){
obj2[x]=obj[x]
};
obj2.name = 456;
obj2.list.push(6,7,8);
obj2.info.title = '我是obj2的标题';
console.log(obj2.name,obj.name) //456,123
console.log(obj2.list,obj.list) //[1,2,3,4,5,6,7,8],[1,2,3,4,5,6,7,8]
console.log(obj2.info.title,obj.info.title)//我是obj2的标题,我是obj2的标题

3,Object.assign

ES6中的Object.assign方法,Object.assign是ES6的新函数。Object.assign()方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。

Object.assign(target, …sources)

target:目标对象。

sources:任意多个源对象。

返回值:目标对象会被返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var obj = {
name:123,
list:[1,2,3,4,5],
fn(){
alert(this.name)
},
info:{
title:'标题',
subtitle:'副标题'
}
};
var obj2 = Object.assign({},obj);
obj2.name = 456;
obj2.list.push(6,7,8);
obj2.info.title = '我是obj2的标题';
console.log(obj2.name,obj.name) //456,123
console.log(obj2.list,obj.list) //[1,2,3,4,5,6,7,8],[1,2,3,4,5,6,7,8]
console.log(obj2.info.title,obj.info.title)//我是obj2的标题,我是obj2的标题

三、深拷贝

深拷贝就会拷贝多层,即使是嵌套了对象,也会都拷贝出来。

深拷贝和浅拷贝最根本的区别在于是否获取了一个对象的复制实体,而不是引用。举个例子来说,假设B复制了A,当修改B时,看A是否会发生变化,如果A变了,说明是浅拷贝,如果A没变,那就是深拷贝。

1,JSON.parse(JSON.stringify())

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var obj = {
name:123,
list:[1,2,3,4,5],
tel:/^1[345789]\d{9}$/,
time:new Date(),
fn(){
alert(this.name)
},
info:{
title:'标题',
subtitle:'副标题'
}
};
var obj2 = JSON.parse(JSON.stringify(obj))
obj2.name = 456;
obj2.list.push(6,7,8);
obj2.info.title = '我是obj2的标题';
console.log(obj2.name,obj.name) //456,123
console.log(obj2.list,obj.list) //[1,2,3,4,5,6,7,8],[1,2,3,4,5]
console.log(obj2.info.title,obj.info.title)//我是obj2的标题,标题
console.log(obj2.tel,obj.tel)//{}, /^1[345789]\d{9}$/
console.log(obj2.time,obj.time)//2021-03-22T07:58:26.788Z,Mon Mar 22 2021 15:58:26 GMT+0800 (中国标准时间)
obj2.fn() //Uncaught TypeError: obj2.fn is not a function
看似实现了对obj对象的深拷贝,但这样导致了fn事件的丢失、正则失效、时间格式发生变化

2,递归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function deepCopy(obj) {
if (typeof obj === 'object') {
var result = obj.constructor === Array ? [] : {};
for (var i in obj) {
result[i] = typeof obj[i] === 'object' ? deepCopy(obj[i]) : obj[i];
}
} else {
var result = obj;
}
return result;
}
var obj = {
name:123,
list:[1,2,3,4,5],
fn(){
alert(this.name)
},
info:{
title:'标题',
subtitle:'副标题'
}
};
var obj2 = deepCopy(obj)
obj2.name = 456;
obj2.list.push(6,7,8);
obj2.info.title = '我是obj2的标题';
console.log(obj2.name,obj.name) //456,123
console.log(obj2.list,obj.list) //[1,2,3,4,5,6,7,8],[1,2,3,4,5]
console.log(obj2.info.title,obj.info.title) //我是obj2的标题 标题
obj2.fn(); //alert(456)
不仅实现了对array和object对象的深拷贝,还实现了对function的拷贝。