###js中的数据类型
js中的数据类型包含两大类:
1.基本类型:string、number、boolean、undefined、null、symbol
2.引用类型:object、array、function
两种数据类型的区别?
1.存储方式不同:基础类型名和值都存储在栈内存中,而引用类型的值存储在堆内存中,栈内存中存储一个指针指向堆内存中的值;
2.赋值类型不同:基本类型是简单赋值,会创建一个新的内存,一个改变不会影响另一个数据,但是引用类型赋值的是引用,它们指向同一个堆内存地址,其中一个改变,会影响另一个数据改变;
let a =1;
let b = a;
b = 3;
console.log(a,b); //1 3
let c = {};
let d = c;
d.name = "test";
console.log(c,d); //{name:"test} {name:"test"}
3.基本类型不可添加属性和方法,引用类型可以;
4.基本类型的值不可改变,它只是改变啦指向,引用类型可以改变值;
5.基本类型的比较是值得比较,引用类型是引用的比较
let a = 1;
let b = 1;
console.log(a == b); //true
let c = {};
let d = {};
console.log(c == d); //false
//虽然c和d都是{},但是由于引用指向的堆内存不同,所以两者不相等
###区分数据类型的方法
1.typeOf():缺点是无法判断null和数组,两者都会输出Object
为什么typeof null会输出object?这是因为js数据类型在底层都是以二进制进行存储的,如果前三位都是0,则会被typeof判定为object,二null的二进制都是0,所以会被typeof判定为是object类型。
2.instanceOf():缺点是不可以检测基本数据类型,而且检测数组等于Object也会为true。
instanceOf原理:是通过左侧对象的隐式原型__proto__在原型链上向上一层层查找,找到右侧构造函数的原型对象属性prototype就返回true。
手写一个instanceOf:
function myInstanceOf(obj,func){
//判断是否为基础类型,基础数据类型直接返回false
if(!['function','object'].includes(typeof obj) || obj == null){
return false;
};
let proto = obj.__proto__;
let protoType = func.prototype;
while (proto !== protoType) {
proto = proto.__proto__;
if(proto == null){
return false;
}
};
return true;
};
console.log(myInstanceOf({}, Object));
3.Object.prototype.toString.call():可以检测所有类型
###浅拷贝和深拷贝
浅拷贝:如果是基本类型,则复制值,如果是引用类型,则复制其引用地址,两者的引用地址指向同一个堆内存;
实现浅拷贝的方法:扩展运算符和Object.assign()
深拷贝:深拷贝会创建一个新的对象,并递归复制所有层级的属性
实现深拷贝的方法:递归和JSON.stringify()/JSON.parse()。
补充:
1.es6中的Object.assign(target,source1,source2),assign方法用于合并对象,第一个参数是目标对象,后面都是源对象,如果存在同名属性,后面的会覆盖前面的。
let target = {a:1};
let source1 = {b:2};
let source2 = {c:3};
let source3 = {c:4};
Object.assign(target,source1,source2,source3);
console.log(target); //{a:1,b:2,c:4}