引言:探索 JavaScript 的奇妙世界
JavaScript,作为现代网页开发的核心语言之一,其灵活性和强大功能令人赞叹。然而,要真正掌握这门语言,理解它的数据类型是至关重要的第一步。今天,我们将一起深入探讨 JavaScript 的八种数据类型,并特别关注 ES6 新增的数据类型——Symbol,揭开它神秘的面纱。
一、JavaScript 的数据类型概览
在开始我们的探险之前,让我们先快速浏览一下 JavaScript 中的八种数据类型。它们分别是:
-
简单数据类型(Primitive Types):
- String
- Number
- Boolean
- Undefined
- Null
- BigInt
- Symbol
-
复杂数据类型(Reference Type):
- Object
简单数据类型存储的是直接值存放在栈区,而复杂数据类型则存储的是引用地址,具体的数据存放在堆区。这种区分类似于我们日常生活中的实体书与图书馆卡片的区别——实体书就像是简单数据类型,你可以直接阅读;而图书馆卡片则是复杂数据类型,你需要通过它找到书籍的位置。
刻意练习:编写一个 add 函数
为了更好地理解这些概念,让我们从一个简单的任务开始:编写一个函数来计算两个数字相加的结果。这个练习不仅有助于巩固基础知识,还能教会我们如何进行类型检查,确保输入参数符合预期。
我们来看下面的代码,编写一个add函数,相信大家都能写出这样的,但是这样真的正确吗?
function add(a, b) {
if (typeof a !== 'number') {
throw new Error('参数类型错误');
}
return a + b;
}
当我们调用add(1,NaN)会得到一个什么结果呢?答案是NaN,为什么呢?我们来看以下代码来解释
const num1=NaN
console.log(Typeof num1)//number
NaN的数据类型也是Number,所以能绕过我们的检测,NaN又是什么呢?我们来看AI的解释
在JavaScript中,NaN代表"Not-a-Number",即“非数字”。这是一个特殊的数值类型,主要用于表示试图将非数字值作为数字处理的情况。例如,当你尝试进行一个数学运算,而这个运算的结果无法定义为一个标准的数字时,就会得到NaN。比如0除以0,或者尝试将一个无法转换成数字的字符串转换为数字(如parseInt("blabla"))。 尽管NaN的名字中包含“非数字”,但在JavaScript中它实际上是一个属于Number类型的特殊值。这意味着typeof NaN返回的是"number",这可能会让人感到有些混淆。
简单来说NaN是我们的错误运算产生的结果,也属于number数据类型,我们再来看看JS当中哪些常见操作会产生NaN的结果
console.log(0 / 0);
// 平方根 sqrt(-1) NaN
console.log(Math.sqrt(-1)); // js 内置的Math 对象
console.log(parseInt('123'), parseInt('a123'), parseInt('123a'));// 123,NaN,123 会由一点晕,容我慢慢解释
console.log(Number(undefined));// NaN
console.log(NaN === NaN); // false Not a Number 不是数字的方式有很多种
console.log(typeof NaN);
错误的数学运算就会产生NaN,可能大家对console.log(parseInt('123'), parseInt('a123'), parseInt('123a'));// 123,NaN,123 会有一点晕,容我慢慢解释
🧠 首先,什么是 parseInt?
parseInt(string, radix) 是 JavaScript 中用于将字符串解析为整数的函数。
它的基本规则是:
- 从字符串的第一个字符开始解析。
- 遇到不能识别为数字的字符时停止。
- 忽略后面的字符,返回已经解析到的部分。
- 如果第一个字符就不能解析成数字,则直接返回
NaN(Not-a-Number)。
这就很清晰的解释了原因,一但解析到不为数字字符的字符就停止解析,这也很清晰的解释了是上述的结果
我们也就很清晰的明白了
function add(a, b) {
if (typeof a !== 'number') {
throw new Error('参数类型错误');
}
return a + b;
}
add(1,NaN)//NaN
一个数与运算出错的number相加当然还是NaN
那我们就得解决这个问题
function add(a, b) {
if (typeof a !== 'number' || typeof b !== 'number' || isNaN(a) || isNaN()来解决(b)) {
throw new Error('参数类型错误');
}
// 参数的校验
return a + b;
}
console.log(add('1', 2));
我们引入isNaN()来解决,isNaN()就是判断是不是NaN类型,是就返回false,不是就返回true,这样就很好的解决了NaN的问题
我们再来聊聊JS数据类型
其实JS的数据类型也可以说成由7种
当然说成8种是正确的,我们只是细分一下
究竟是哪7种呢
七种 string boolean null undefined symbol numeric6种primitive 简单类型,其中numeric包括bigint和number归为numberic一类,这是我们需要了解的 object
7种就是我们把bigint和number归为numberic一类,这是我们需要了解的,要不然以后有人提及这个概念,你可能会和人家吵起来哈哈哈哈
二、深入了解简单数据类型
接下来,我们将逐一了解每一种简单数据类型的特点和用途。
String 字符串
字符串是最常用的简单数据类型之一,用于表示文本信息。在 JavaScript 中,我们可以用双引号、单引号或反引号(模板字符串)来定义字符串。
Number 数字
Number 类型用来表示整数和浮点数。值得注意的是,在 JavaScript 中,所有数字都被视为浮点数处理,这有时候可能会导致一些意想不到的行为。
Boolean 布尔值
布尔值只有两种可能的状态:true 和 false。布尔值常用于逻辑判断中,例如条件语句。
Undefined 未定义
当一个变量被声明但没有赋值时,默认值就是 undefined。它表明该变量目前没有任何具体的值。
Null 空值
Null 是另一种特殊的简单数据类型,表示“无”或者“空”。与 undefined 不同的是,null 表示有意为之的空值。
BigInt 大整数
BigInt 是 ES11 引入的一种新的简单数据类型,允许我们表示任意长度的整数,解决了传统 Number 类型只能精确表示到 253−1253−1 的限制。
Symbol 符号
最后,我们要重点介绍的是 Symbol。它是 ES6 新增的数据类型,代表独一无二的值。每一个通过 Symbol() 创建的实例都是唯一的,即使它们具有相同的描述。
三、Symbol:JavaScript 中的新星
正如前文所述,Symbol 是一种非常特殊的数据类型,主要用于创建独一无二的标识符。这使得它成为实现私有属性的理想选择,尽管 JavaScript 并不支持真正的私有属性。
使用 Symbol 实现对象的隐私保护
由于每个 Symbol 都是唯一的,我们可以利用这一点来为对象添加不可枚举的属性,从而达到保护对象内部状态的目的。
const ID = Symbol('id');
const user = {
name: 'Alice',
[ID]: 123,
};
console.log(user.name); // 输出 "Alice"
console.log(user[ID]); // 输出 123
在这个例子中,尽管我们可以通过显式访问获取到 user[ID] 的值,但在遍历对象时,这个属性是不会被列出的。
比如以下代码:
const ID = Symbol('id')
const sex = '男'
const age = Symbol('age')
const user = {
"name": 'Alice',
"age": 2,
[age]: 18,
// [sex]: '男',
// key 是独一无二的
// 当我们在大厂,如果我们要去修改别人的代码中的对象
// 对象动态的 不希望出错,
[ID]: 123,
}
for (let key in user) {
// 遍历对象
console.log(key, user[key], '--------');// name Alice -------- age 2 -------- 并不会输出[age]: 18 和 [ID]: 123 // 对象的隐私,内部需要,不希望外界调用
}
Symbol 在状态管理中的应用
另一个常见的应用场景是在状态管理中使用 Symbol 来定义不同的状态标识符。这样不仅可以提高代码的可读性,还能有效防止状态冲突。
const STATUS = {
READY: Symbol('ready'),
RUNNING: Symbol('running'),
DONE: Symbol('done')
};
let state = STATUS.READY;
if (state === STATUS.READY) {
console.log('Ready!');
}
🌟 什么是枚举类型?
枚举(Enum) 是一种数据结构,它由一组命名的常量组成。通常用于表示固定的、有限的状态或选项。
在很多语言中(如 TypeScript、Java、C#),有原生的 enum 关键字支持枚举类型,但在 JavaScript(ES6+)中并没有原生的 enum 类型,所以我们可以用对象 + Symbol 或字符串模拟实现一个枚举。
💡 枚举类型的优点
| 特性 | 说明 |
|---|---|
| 可读性强 | STATUS.READY 比写魔法数字 1 更容易理解 |
| 避免冲突 | 使用 Symbol 确保每个值唯一,避免字符串重复带来的错误 |
| 易于维护 | 所有状态集中管理,方便修改和扩展 |
🧠 举个例子对比一下
❌ 不用枚举时:
let state = 'ready';
if (state === 'read') { // 容易打错
console.log('ready');
}
容易出错,比如 'read' 和 'ready' 写错了不好查。
✅ 用枚举后:
const STATUS = {
READY: Symbol('ready'),
RUNNING: Symbol('running'),
DONE: Symbol('done')
};
let state = STATUS.READY;
if (state === STATUS.READY) {
console.log('ready');
}
清晰、安全、不易出错。
结语
通过对 JavaScript 数据类型的全面解析,特别是对 Symbol 的详细介绍,我们希望你已经对这门语言有了更深的理解。无论是构建健壮的应用程序,还是追求优雅的代码设计,掌握这些基本概念都将是你成为一名优秀开发者的关键一步。继续探索,不断学习,你会发现编程世界的无限可能性正等待着你去发掘。