大厂面试官(6):请你说出JavaScript中有几种数据类型

394 阅读6分钟

还是一句老话,大厂看中的不仅是你高超的技术,反而更看重你的基础。所以我们不能只主攻算法和高级的用法,更应该注意一些基础,底层的基础。今天来带大家细说一下JavaScript中的数据类型。希望大家能从中收获些什么。

什么是数据类型???

在JavaScript中,数据类型是用来定义变量可以存储的数据种类。因为JavaScript是一种动态类型的语言,所以我们在声明变量时不需要明确它的数据类型,因为我们的引擎会根据赋给变量的值自动确定它的数据类型.

数据类型的种类

JavaScript的数据类型主要分为两类:简单数据类型(也叫原始数据类型)复杂数据类型

简单数据类型中含有:Number、String、Boolean、Null、Undefined、Symbol、Bigint

复杂数据类型中含有:Object

此时面试官问你:JavaScript一共有几种数据类型?

此时,高手会回答8种!

但是!高高手会回答7种

此时你可能会很懵:7+1不是等于8吗?为什么回答7更厉害呢?

这里就有一个细节了。

Number和Bigint都属于一个类中,这个类就是Numeric。这是一个很隐秘的细节,往往就是你和高手之间的差距。

简单数据类型了解

number

普通的咱们就不多说,我们只说细节和重点

let a = 0.1;
let b = 0.2;
console.log(a+b);

大家应该都认为输出0.3吧。这里又有一个坑了:

image.png 此时输出的结果是这样的:这是为什么呢?

虽然类型名称叫number可他却不擅长于计算。在JavaScript中,我们的计算方式是以二进制计算。当数字为小数时,在二进制中是无限循环的小数

  • 0.1 的二进制表示大约是 0.00011001100110011001100110011001100110011001100110011010

  • 0.2 的二进制表示大约是 0.0011001100110011001100110011001100110011001100110011010

    此时相加便等于上面的结果。

Null

在我们的潜意识中,null的意思就是。但空值是不是也给一个变量赋值了呢?

答案是肯定的。

null是一个可以赋值给对象的一个特殊值。

let a = null;
console.log(a);

此时输出

image.png 另外的,他还可以显示内存回收

// 堆内存
let largeObject={
    data:new Array(100).fill('a')
}
// 释放内存 垃圾回收
largeObject=null;

语法咱们就不多说,fill把数组内都赋值为a。

但这就牵扯到一个新的问题。

栈内存堆内存

简单来说

  • 栈内存用于存储变量的名称和值(如果是基本类型)或引用(如果是对象)。
  • 堆内存用于存储对象的实际数据。

a8178647a94e269c5760d94d57b77486.png

9d8add33a34c020d88067ccb03ad72ac.png

let a = 1;
// 拷贝
let b = a;
b=3;
console.log(a,b) // 1 3

图片来自稀土掘金技术社区

在上面代码中。我们先声明了一个变量largeObject,此时变量存储在栈内存中。

然后,我们创建了一个对象data:new Array(100).fill('a'),此时对象存储在堆内存中。

最后我们引用赋值:largeObject 存储的是指向堆内存中对象的引用

此时我们就进行了释放内存,垃圾回收的步骤

largeObject = null;

  • 重新赋值:将 largeObject 重新赋值为 null。此时,栈内存中 largeObject 的值从原来的引用变成了 null

此时我们的堆内存中对象被孤立。垃圾回收器会在未来的某个时刻自动回收这些孤立对象,但这个过程是后台进行的,不会影响代码的输出

image.png

引用了对象中没有的属性:

let person = { 
name: "John",
age: null
};
console.log(person.age); // 输出 null

undefined

有人可能认为,null和undefined很相似,都是表示的特殊值。这是有道理的,但他们的语义和使用场景有一些重要的区别。

当我们引用声明了但未赋值的变量时:

let x;
console.log(x); // 输出 undefined

类似的未定义的属性:

let obj = {};
console.log(obj.name); // 输出 undefined

函数参数未提供:

function printName(name) {
console.log(name); 
} 
printName(); // 输出 undefined

symbol

symbol是es6后出现的数据类型,用于创建唯一的标识符。有函数一样的外观。

唯一性:即使描述的字符串相同,也会输出false

let sym1 = Symbol("key");
let sym2 = Symbol("key");
console.log(sym1 === sym2); // 输出 false

boolean

表示真或假,值为 true 或 false

bigint

这个类型也是es6才引入的。用于处理数据过大的问题 当我们输入:

let num = 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999;
let num2=41814854854854888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888844854451451442;
console.log(num+num2);

此时会出现

image.png 数值一点都不准确啊。

想让数值变得更准确,只需要在数据后加n,则创建了bigint类型,可以得到准确值

image.png 注意事项

  1. 类型检查BigInt 是一个独立的类型,不能与 Number 类型直接进行比较或运算。
let num = 1234567890123456789012345678901234567890;
let bigInt = 1234567890123456789012345678901234567890n;
console.log(num === bigInt); // 输出 false

复杂数据类型了解

object可以包含所有复杂数据类型,数组,函数,正则表达式等。这些都很常见,就不过多介绍了。

区别

简单数据类型与复杂数据类型有哪些区别?

简单数据类型 一眼就能看出其值

函数、数组等有很多特性无法表达

还有一个,简单数据类型进行的是值传递,直接储存在栈内存中,是不可改变的

复杂类型则是引用传递,数据存储在堆内存中,变量存储的是引用,可以改变

typeof

用typeof可以分析我们输入数据类型的类型。

console.log(typeof 1);
console.log(typeof "hello");
console.log(typeof true);
console.log(typeof 12n);
console.log(typeof Symbol());
console.log(typeof null);
console.log(typeof undefined);
console.log(typeof function(){})

此时输出: image.png

typeof 除了null 之外的简单数据类型 都可以得到正确的结果

这是为什么呢?

这是因为JavaScript在最初设计时留下的bug。当时,null 被设计为表示空对象指针,因此 typeof null 返回 "object" 是为了与 C/C++ 中的 NULL 指针保持一致。

为了保持兼容性,就一直这样使用了。

结语

这就是关于数据类型的一些说明,希望大家可以从中收获。