七上八下:彻底掌握js的数据类型

467 阅读6分钟

引言

现如今js中一共有几种数据类型,这是大厂面试中面试官非常喜欢问的一个问题,许多大佬高手可能会不假思索的说出8种分别是Number ,string ,boolean ,null ,undefined ,symbol ,bigint和object,但我想更有经验的程序员应该会讲7种,因为Numberbigint 可以归为一类numeric。看下图,有图有真相 [doge]

iwEcAqNwbmcDAQTRB_wF0QkUBrCwNxaOikCytAclU7Ot_B8AB9IoJU2sCAAJomltCgAL0gAHId8.png_720x720q90.jpg

简单数据类型和复杂数据类型

通常情况下,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,不信请看下面

image.png 相信许多朋友看到这人都懵了,心想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);

image.png

可以清晰的看到打印的是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(){})

image.png

可能有朋友立马发现了第12行打印的竟然是object!不用大惊小怪,因为这只是一个历史遗留问题,据说JavaScript 的设计者 Brendan Eich 在设计语言时只花了差不多一个星期左右就把js搞出来了,所以难免会有些不当的地方,在 JavaScript 的早期版本中,null 被设计为一个特殊的对象引用,表示“空”或“无”。所以它的结果是object,这个问题到现在也没有解决,通俗的来说这就是js留下的一个小bug而已,我们只要了解即可。

如果本篇文章对你有些许帮助的话,点个赞吧(深夜码字不易啊)

c224676594aae6804009e3fe521b122.jpg