引言
现如今js中一共有几种数据类型,这是大厂面试中面试官非常喜欢问的一个问题,许多大佬高手可能会不假思索的说出8种分别是Number ,string ,boolean ,null ,undefined ,symbol ,bigint和object,但我想更有经验的程序员应该会讲7种,因为Number和bigint 可以归为一类numeric。看下图,有图有真相 [doge]
简单数据类型和复杂数据类型
通常情况下,JavaScript的数据类型被划分为两大类:简单数据类型(Primitive Types)和复杂数据类型(Reference Types)。当然也有把这个叫为原始数据类型和引用数据类型的,这二者并没有什么区别,只是叫法不同而已。除了object(数组 ,函数)为复杂数据类型,其他几种都是简单数据类型。
null 和 undefined
许多小白一直搞不清这两者的区别,觉得不都表示空、没有嘛,直接删掉一个不就行了,但诸君,这两者完全是不同的东西,下面请听我娓娓道来
null
- 表示一个空值或不存在的对象,是一个可以赋给变量的特殊值
- 用途
- 用于表示一个有意设置为空的对象引用。
- 通常表示某处应该有一个值,不过目前没有值罢了
- 可以用来清空一个变量的值(释放内存,垃圾回收)
let a = null;
console.log(a); // null
let obj = {
name: "Alice",
address: null
};
console.log(obj.address); // null
let larageObject = {
data : new Array(100000000).fill("a")
};
largeObject = null;//释放内存,垃圾回收
undefined
- 表示一个未初始化或不存在的变量值
- 用途
- 当声明一个变量但未赋值时,该值默认为undefined
- 表示某个对象属性不存在
- 函数没有返回值时,默认返回undefined
- 访问不存在的数组索引或对象属性时,返回undefined
let a; // 未初始化
console.log(a); // undefined
let obj = {};
console.log(obj.property); // obj的property不存在,返回undefined
function noReturn() {}
console.log(noReturn()); // undefined
let arr = [1, 2, 3];
console.log(arr[5]); // undefined
Symbol
- 它是从es6开始引入的,用于创建唯一的标识符,可以以函数的形式创建。即使两个Symbol的标签一样它们的值也绝对不一样
console.log(Symbol('马斯克') === Symbol('马斯克')); // false
- Symbol值可以作为对象的属性名,这些属性不会出现在for...in循环中,也不会被Object.keys()方法返回,但可以通过Object.getOwnPropertySymbols()方法获取。
let obj = {
[Symbol('a')]: 'valueA',
[Symbol('b')]: 'valueB',
prop: 'valueProp'
};
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(a), Symbol(b)]
console.log(Reflect.ownKeys(obj)); // ['prop', Symbol(a), Symbol(b)]
bigint
由于js是一门弱类型语言,虽然它具有强大的表现力,但这也无法改变它不擅长计算的事实,这也就导致它在计算时会出现许多低级错误
请看下面这段代码
let a = 0.1;
let b = 0.2;
console.log(a + b);
你是不是第一感觉就是会结果是0.3,那你就大错特错了,答案会是0.3000000000000000004,不信请看下面
相信许多朋友看到这人都懵了,心想js连这个都不会算吗?其实这是由于在大多数编程语言中,浮点数是以二进制形式存储的。而有些十进制小数无法精确的表示成二进制(因为有些小数转换成二进制后会有一个无限循环的小数部分),这也就导致了计算过程中的误差,这种小数的误差可以使用
toFixed()方法或者 Math.round() 来格式化结果。这不是我们今天要主讲的,好了言归正传,js在计算那些超级大的数时同样有这些问题,这个时候就可以用bigint来解决了
BigInt 是 JavaScript 中的一种数值类型,从 ES11(ES2020)开始引入。BigInt 用于表示任意大小的整数,解决了 Number 类型在处理大整数时的精度问题。
let num1 = 999999999999999999999999999999999999999999999999999999999999999
let num2 = 123456789098765433467324577654789008733233456899003466788924243
console.log(num1 + num2); // 1.1234567890987655e+63
如图所示,这个结果显然是错的,那怎么样才能让它运行正确呢?也简单,只要在数字后面加个n就行了
let a = 1234567890123456789012345678901234567890n;
let b = 987654321098765432109876543210987654321n;
let sum = a + b;
console.log(sum); // 1111111110111111111011111111101111111111n
简单数据类型和复杂数据类型区别
- 简单数据类型一旦创建,其值就
不能改变。它是直接存储在栈内存中的,复制时是复制值本身 - 复杂数据类型是可以包含多个值的复杂结构所以它的值是
可变的,复杂数据类型是存储在堆内存中,栈内存中仅保存指向堆内存中实际数据的指针,复制时是复制指向堆内存的地址,而不是数据本身。请看下面的代码:
let obj = {
name: "小明",
job: "前端开发工程师",
company: "字节"
hometown:"南昌"
}
let a = 1
// 拷贝
let b = a
b =3
// 引用式赋值s
let obj2 = obj;
obj2.name = "小刚"
console.log(a,b);
console.log(obj,obj2);
可以清晰的看到打印的是a,b的值发生了改变,这说明简单数据类型的值式拷贝,最后一行打印的是两个小刚而不是一个小明和一个小刚,这足以说明复杂数据类型的复制是引用式赋值
typeof 简介
typeof是js中的一种操作符,可以用来确定一个变量或表达式的类型。
let a = 1
// typeof js 类型 运算符
// console.log(typeof a,typeof(a));
// The Good Parts 什么好的,什么是坏的
console.log(typeof a)
console.log(typeof "hello ")
console.log(typeof true)
console.log(typeof 12n)
console.log(typeof Symbol())
console.log(typeof undefined)
console.log(typeof null)
console.log(typeof function(){})
可能有朋友立马发现了第12行打印的竟然是object!不用大惊小怪,因为这只是一个历史遗留问题,据说JavaScript 的设计者 Brendan Eich 在设计语言时只花了差不多一个星期左右就把js搞出来了,所以难免会有些不当的地方,在 JavaScript 的早期版本中,null 被设计为一个特殊的对象引用,表示“空”或“无”。所以它的结果是object,这个问题到现在也没有解决,通俗的来说这就是js留下的一个小bug而已,我们只要了解即可。
如果本篇文章对你有些许帮助的话,点个赞吧(深夜码字不易啊)