面试问起JavaScript的数据类型,是不是还是张嘴就是吧啦吧啦的说基本数据类型5种,string、number、boolean、null、undefined;引用数据类型2种,object,array。
其实,JavaScript 中有许多数据类型,主要分为两大类:基本数据类型(Primitive Data Types)和引用数据类型(Reference Data Types)。以下是它们的一些常见类型:
基本数据类型:
- 字符串(String): 用于表示文本。
javascript
// 应用场景:处理文本内容
let greeting = "Hello, World!";
console.log(greeting);
- 数字(Number): 包括整数和浮点数。
javascript
// 应用场景:进行数学计算,例如计算购物车总价
let price = 49.99;
let quantity = 2;
let total = price * quantity;
console.log("Total price: " + total);
- 布尔(Boolean): 代表逻辑上的真或假。
javascript
// 应用场景:控制流程,例如根据用户是否登录显示不同内容
let isLoggedIn = true;
if (isLoggedIn) {
console.log("Welcome back!");
} else {
console.log("Please log in.");
}
- 空值(Null): 表示一个空值对象。
javascript
// 应用场景:初始化变量,表示目前没有具体数值
let data = null;
console.log("Data is null: " + (data === null));
- 未定义(Undefined): 表示未初始化的变量。
javascript
// 应用场景:声明变量但未赋值,或者读取对象中不存在的属性
let undefinedVar;
console.log("Undefined variable: " + undefinedVar);
- 符号(Symbol): 用于创建唯一的标识符。
javascript
// 应用场景:创建唯一的对象键,避免键名冲突
const uniqueKey = Symbol("uniqueKey");
let myObject = {};
myObject[uniqueKey] = "Some value";
console.log(myObject[uniqueKey]);
const uniqueKey1 = Symbol("uniqueKey");
const uniqueKey2 = Symbol("uniqueKey");
console.log(uniqueKey1 === uniqueKey2); //false
console.log(typeof uniqueKey1); //symbol
let symbol1 = Symbol.for('aaa'); // 新建一个与该键关联的 symbol,并放入全局 symbol 注册表中
let symbol2 = Symbol.for('aaa'); // 从运行时的 symbol 注册表中找到对应的 symbol,如果找到了,则返回它
console.log(symbol1 === symbol2); // true
- 最大数字(BigInt): 用于表示任意大的整数。
BigInt 是 JavaScript 中的一种数据类型。它是在 ECMAScript 2020 标准中引入的,用于表示任意精度的整数。BigInt 可以用来表示比 Number 类型更大范围的整数,而不会导致溢出。BigInt 是 JavaScript 中的一种数据类型。它是在 ECMAScript 2020 标准中引入的,用于表示任意精度的整数,它提供了一种方法来表示大于 2^53 - 1
的整数。BigInt 可以用来表示比 Number 类型更大范围的整数,而不会导致溢出。 以下是 BigInt 的简单示例:
javascript
const bigInteger1 = Number.MAX_SAFE_INTEGER + 1;
const bigInteger2 = Number.MAX_SAFE_INTEGER + 2;
console.log(bigInteger1); //9007199254740992
console.log(bigInteger2); //9007199254740992
console.log(bigInteger1 === bigInteger2) //true
//给干溢出了
const bigInteger = BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1);
console.log(bigInteger); //9007199254740992n
在这个例子中,我们使用 BigInt 来表示一个比 Number.MAX_SAFE_INTEGER
更大的整数,而不会丢失精度。需要注意的是,BigInt 的字面量表示形式是在整数后面添加 "n",例如 10n
表示 BigInt 类型的 10。
javscript
const bigIntegerLiteral = 10n;
console.log(bigIntegerLiteral); // 10n
console.log(typeof bigIntegerLiteral); // bigint
引用数据类型:
- 对象(Object): 包括普通对象、数组、函数等。
javascript
// 应用场景:表示复杂的数据结构,例如用户信息
let user = {
name: "John",
age: 30,
address: {
city: "Example City",
country: "Example Country"
}
};
console.log("User name: " + user.name);
- 数组(Array): 用于存储有序的数据集合。
javascript
// 应用场景:存储有序的数据集合,例如保存列表数据
let colors = ["red", "green", "blue"];
console.log("First color: " + colors[0]);
- 函数(Function): 具有可执行的代码块的对象。
javascript
// 应用场景:封装可重用的代码块,例如处理用户点击事件
function handleClick() {
console.log("Button clicked!");
}
// 在事件监听中使用
document.getElementById("myButton").addEventListener("click", handleClick);
- 日期(Date): 用于表示日期和时间。
javascript
// 应用场景:处理日期和时间,例如显示最后修改时间
let lastModified = new Date();
console.log("Last modified on: " + lastModified.toLocaleDateString());
// Last modified on: xxxx/x/xx(当前时间)
- 正则表达式(RegExp): 用于处理文本模式匹配。
javascript
// 应用场景:处理文本模式匹配,例如验证用户输入
let pattern = /hello/;
console.log("Pattern matches: " + pattern.test("Hello, World!")); // Pattern matches: false
正则表达式感觉像是一种"魔法"一样,用事先定义好的一些特定字符、及这些特定字符的组合,组成一个 "规则字符串" ,对字符串进行过滤。玩明白还是太费劲了。还好人和动物最大的区别就是会使用工具,介绍一个常用的正则表达式vscode插件any-rule:
再复杂的规则写不出?或者是有现成的正则表达式看不懂?那还好咱生活在4202年,chatgpt写这些玩意可太熟练了。
- Map 和 Set: 用于存储键值对和唯一值的集合。
Map
对象保存键值对,并且能够记住键的原始插入顺序。任何值(对象或者原始值)都可以作为键或值。
Set
对象允许你存储任何类型(无论是原始值还是对象引用)的唯一值。 Set
对象是值的合集(collection)。集合(set)中的元素只会出现一次,即集合中的元素是唯一的。
javascript
// 应用场景:管理键值对和唯一值的集合,例如存储用户偏好设置
let userPreferences = new Map();
userPreferences.set("theme", "dark");
userPreferences.set("language", "english");
console.log(userPreferences); //{'theme' => 'dark', 'language' => 'english'}
let uniqueNumbers = new Set([1, 2, 3, 4, 5, 1]);
console.log("Unique numbers: " + [...uniqueNumbers]); //Unique numbers: 1,2,3,4,5
这些数据类型在 JavaScript 中用于存储和操作不同种类的数据。基本数据类型是按值传递的,而引用数据类型是按引用传递的。这意味着基本数据类型直接存储值,而引用数据类型存储的是对值的引用。
为什么JavaScript的数据类型要分为基本数据类型和引用数据类型?
JavaScript的数据类型分为基本数据类型和引用数据类型,主要是为了更有效地管理内存和提高程序的性能。这两种类型在处理方式上有一些重要的区别:
-
内存管理效率:
- 基本数据类型: 基本数据类型是按值传递的,它们直接存储数据的值。这意味着基本数据类型的值被直接存储在变量中,而且变量之间的赋值是独立的。这样的存储方式使得基本数据类型的操作更为高效。
- 引用数据类型: 引用数据类型是按引用传递的,它们存储的是对内存中实际数据的引用。这样的存储方式意味着多个变量可以共享相同的数据,但也增加了对内存的管理复杂性。
-
复制行为:
- 基本数据类型: 当将一个基本数据类型的值赋给另一个变量时,实际上是复制了该值。修改其中一个变量不会影响另一个。
- 引用数据类型: 复制一个引用类型的变量时,复制的是对实际数据的引用,而不是数据本身。这导致多个变量可以指向相同的数据,修改其中一个变量可能会影响其他引用相同数据的变量。
-
比较行为:
- 基本数据类型: 两个基本数据类型的比较是比较它们的值是否相等。
- 引用数据类型: 两个引用数据类型的比较通常是比较它们是否引用相同的对象,而不是对象的内容。
-
存储大小:
- 基本数据类型: 基本数据类型的值在内存中占用固定的空间,大小是固定的。
- 引用数据类型: 引用数据类型的大小可能会变化,因为它们存储的是对象的引用,而对象的大小可能不固定。
分为基本数据类型和引用数据类型有助于理解变量之间的赋值、比较和传递行为,同时也使得 JavaScript 引擎能够更有效地管理内存。这种设计有助于平衡灵活性和性能的需求。
从堆栈的角度去理解基本数据类型和引用数据类型
在 JavaScript 中,有两个主要的内存区域:堆(Heap)和栈(Stack)。
基本数据类型(按值传递):
- 存储位置:
- 栈: 存储基本数据类型的变量和它们的值。值直接存储在栈中。
- 复制:
- 当将一个基本数据类型的值赋给另一个变量时,复制的是值本身。
- 释放:
- 当变量超出作用域时,其在栈上的空间会被立即释放。
引用数据类型(按引用传递):
- 存储位置:
- 栈: 存储引用数据类型变量的引用。引用指向堆中实际的数据。
- 堆: 存储引用数据类型的实际数据。堆是一个动态分配的区域,存储对象的属性和方法等。
- 复制:
- 复制引用数据类型时,复制的是引用,而不是实际的数据。
- 释放:
- 当引用数据类型不再被引用时,JavaScript 的垃圾回收机制会定期检测并释放不再使用的堆内存。
这种基于堆栈的存储和管理方式有助于理解为什么基本数据类型在赋值和传递时是按值传递的,而引用数据类型是按引用传递的。基本数据类型直接存储在栈中,而引用数据类型在栈中存储引用,实际数据存储在堆中。这种区分有助于更好地理解 JavaScript 中的内存管理和变量操作。