基本数据类型有几种,null是对象类型还是基本数据类
1.基本数据类型有 number,string,boolean,null,undefined,symbol(ES6新增的),也称原始数据类型。
2.JS有原始值类型和引用值类型,
- 2.1 原始值类型里面存储的都是值,原始值类型是无法改变的。
var str = "hello";
str[0] = "z"; //无法修改
- 2.2 引用值类型指的是由多个值构成的对象。
一般情况下声明的变量是对象类型的话,会在栈内存中存放着引用地址,该地址会指向堆内存中的内容。
3.JS内存分为堆内存和栈内存,栈内存保存的都是有固定大小、空间的内容。堆内存中存储的都是不固定的内容。
- 字符串是个特例,字符串具有不变性,字符串存储在栈内存中。
4.二者区别
- 4.1 原始值类型保存在栈内存中,可以按值直接访问。
值与值之间是独立存在的,修改一个变量不会影响到其他变量。
var a = 10;
var b = a; //将a的值赋给b
b = 20;
console.log(a); // 10
console.log(b); // 20
基本数据类型赋值过程:
图片来自博主:cc_ccc
- 4.2 引用值类型存放在堆内存中,按照引用访问。
- 每新建一个新的对象,就会在堆内存中开辟一块新的空间
- 如果两个变量保存的是同一个对象引用,当通过一个变量修改属性时,另外一个也会受到影响。
var obj = new Object();
obj.name = "孙悟空";
var obj2 = obj;
obj2.name = "猪八戒";
console.log(obj.name); //猪八戒
console.log(obj2.name); //猪八戒
引用数据类型赋值过程:
图片来自博主:cc_ccc
5.如果两个对象一模一样,但也还是两个对象
- 当比较两个基本数据类型的值时,就是比较数值
- 比较两个引用数据类型时,比较的是对象的内存地址,对象相同,但地址不同,会返回false
6.null不是引用数据类型,是基本数据类型。
深拷贝、浅拷贝
1.深拷贝: 修改新变量的值不会影响原有变量的值,默认情况下基本数据类型都是深拷贝
let num1 = 123;
let num2 = num1;
num2 = 666; // 修改新变量的值
console.log(num1); //123
console.log(num2); /666
2.浅拷贝:修改新变量的值会影响原有的变量的值,默认情况下引用类型都是浅拷贝。
class Person{
name = "jjj";
age = 23;
}
let p1 = new Person();
let p2 = p1;
p2.name = "wdhj"; //修改p2的值影响了p1的值
console.log(p2.name); //wdhj
console.log(p1.name); //wdhj
如何实现引用数据类型的深拷贝(上)
当引用数据类型中保存的都是基本数据类型时
1.方法一(不好)
- 浅拷贝的原因:多个变量指向了同一块存储空间,想要实现深拷贝,可以让每个变量分别指向自己的存储空间
class Person{
name = "mss";
age = 18;
}
let p1 = new Person();
let p2 = new Person();
//因为p1里面的属性都是基本数据类型,所以可以取出p1的name赋值给p2
p2.name = p1.name;
p2.age = p1.age;
p2.name = "mhf";
p2.age = 20;
console.log(p1.name); //mss
console.log(p2.name); //mhf
2.方法二(不好)
- 利用循环来遍历每个属性
class Person{
name = "mss";
age = 18;
}
let p1 = new Person();
let p2 = new Person();
for(let key in p1){ //利用遍历来赋值每个属性
p2[key] = p1[key];
}
p2.name = "mhf";
console.log(p1.name);//mss
console.log(p2.name);//mhf
3.方法三(重点)
- Object的assign()方法接收两个参数,代表含义是将p1中的所有属性拷贝到p2中
class Person{
name = "mss";
age = 18;
}
let p1 = new Person();
let p2 = new Person();
Object.assign(p2,p1);
p2.name = "mhf";
console.log(p1.name);//mss
console.log(p2.name);//mhf
以上三种方法并不能实现真正意义上的深拷贝,因为对象中保存的都是基本数据类型
如何实现引用数据类型的深拷贝(下)
当引用数据类型中保存的都是引用数据类型时
class Person{
name = "mss";//只有name是基本数据类型
cat = {
age: 3,
};
scores = [1,2,3];
}
let p1 = new Person();
let p2 = new Person();
deepCopy(p2,p1);//调用deepCopy函数
p2.cat.age = 666;//修改p2中cat的age属性
console.log(p1.cat.age);//3
//p2的修改并没有导致p1的变化
console.log(p2.cat.age);//666
function deepCopy(target,source) {
//1.遍历拿到source中所有的属性
for(let key in source){
//2.取出遍历到的属性的取值
let sourceValue = source[key];
//3.判断当前的取值是否是引用数据类型
if(sourceValue instanceof Object){ //所有的对象都是Object的实例
//拿到对象的constructor,查看是数组还是对象
//console.log(sourceValue.constructor);
//是数组就new Array,是对象就new Object
//console.log(new sourceValue.constructor);
let subTarget = new sourceValue.constructor;
target[key] = subTarget;
//再次调用拷贝对象中的属性
deepCopy(subTarget,sourceValue);
}else{
//如果是基本数据类型直接添加
target[key] = sourceValue;
}
}
}