跳到主要内容

JavaScript 数据类型

引言

在编程语言中,数据类型是一个基础且关键的概念。JavaScript作为一门动态类型语言,拥有自己独特的类型系统。理解JavaScript的数据类型不仅能帮助你写出更健壮的代码,还能避免许多常见的错误。

本文将详细介绍JavaScript中的各种数据类型,帮助你打下坚实的基础。

JavaScript 数据类型概览

JavaScript有两大类数据类型:

  1. 基本数据类型(原始类型):直接存储简单的数据值
  2. 引用数据类型(对象类型):存储对复杂数据结构的引用

基本数据类型(原始类型)

JavaScript中有7种基本数据类型:

  • Number(数字)
  • String(字符串)
  • Boolean(布尔值)
  • Undefined(未定义)
  • Null(空值)
  • Symbol(符号,ES6新增)
  • BigInt(大整数,ES2020新增)

引用数据类型(对象类型)

JavaScript中的对象类型包括:

  • Object(对象)
  • Array(数组,是特殊的对象)
  • Function(函数,是特殊的对象)
  • Date(日期对象)
  • RegExp(正则表达式对象)
  • Map、Set等(ES6新增)

基本数据类型详解

Number(数字)

JavaScript使用IEEE 754标准的64位浮点数表示所有数字。

javascript
// 整数
let int = 42;
// 浮点数
let float = 3.14;
// 科学计数法
let scientific = 5e3; // 5000
// 特殊值
let infinity = Infinity;
let negInfinity = -Infinity;
let notANumber = NaN; // Not a Number

console.log(typeof int); // "number"
提示

JavaScript中没有整数类型,所有数字都是浮点数,这也是为什么0.1 + 0.2 !== 0.3的原因(浮点数精度问题)。

String(字符串)

字符串是由零个或多个字符组成的文本。在JavaScript中,字符串可以用单引号、双引号或反引号(模板字符串)表示。

javascript
let singleQuotes = 'Hello';
let doubleQuotes = "World";
let backticks = `${singleQuotes}, ${doubleQuotes}!`; // 模板字符串支持插值

console.log(backticks); // "Hello, World!"
console.log(typeof backticks); // "string"

常用字符串方法

javascript
let text = "JavaScript";

console.log(text.length); // 10
console.log(text.toUpperCase()); // "JAVASCRIPT"
console.log(text.substring(0, 4)); // "Java"
console.log(text.indexOf("Script")); // 4

Boolean(布尔值)

布尔类型只有两个值:truefalse,用于表示逻辑值。

javascript
let isActive = true;
let isLoggedIn = false;

console.log(typeof isActive); // "boolean"

以下值在条件语句中会被视为假(falsy):

  • false
  • 0
  • ''(空字符串)
  • null
  • undefined
  • NaN

其他所有值,包括所有对象,即使是空对象{},都被视为真(truthy)。

Undefined

当变量被声明但没有赋值时,它的值是undefined。函数如果没有返回值,默认也返回undefined

javascript
let notAssigned;
console.log(notAssigned); // undefined

function noReturn() {
// 没有return语句
}
console.log(noReturn()); // undefined

console.log(typeof notAssigned); // "undefined"

Null

null表示一个空值或不存在的对象引用。它是一个特殊的值,表示"没有值"或"空"。

javascript
let empty = null;
console.log(empty); // null

// 注意:typeof null的结果是"object",这是JavaScript中的一个历史遗留bug
console.log(typeof empty); // "object"
警告

typeof null返回"object"是JavaScript的一个著名bug,但由于历史原因无法修复,因为这会破坏现有代码。

Symbol(ES6新增)

Symbol是ES6引入的新原始数据类型,表示唯一的、不可变的值,主要用作对象属性的键。

javascript
let id = Symbol("id");
let id2 = Symbol("id");

console.log(id === id2); // false,每个Symbol值都是唯一的

let user = {
name: "John",
[id]: 123 // 使用Symbol作为对象属性
};

console.log(user[id]); // 123
console.log(typeof id); // "symbol"

BigInt(ES2020新增)

BigInt是一种内置对象,可以表示任意精度的整数。

javascript
// 创建BigInt的方法:在整数末尾加n或使用BigInt()构造函数
let bigNumber = 1234567890123456789012345678901234567890n;
let anotherBig = BigInt("9007199254740991");

console.log(bigNumber + 1n); // 1234567890123456789012345678901234567891n
console.log(typeof bigNumber); // "bigint"

引用数据类型详解

Object(对象)

对象是JavaScript中最复杂的数据类型,可以存储各种键值对。

javascript
let person = {
firstName: "John",
lastName: "Doe",
age: 30,
isEmployee: true,
sayHello: function() {
return `Hello, my name is ${this.firstName} ${this.lastName}`;
}
};

console.log(person.firstName); // "John"
console.log(person["lastName"]); // "Doe"
console.log(person.sayHello()); // "Hello, my name is John Doe"

console.log(typeof person); // "object"

Array(数组)

数组是一种特殊类型的对象,用于存储有序的数据集合。

javascript
let fruits = ["Apple", "Banana", "Orange"];

console.log(fruits[0]); // "Apple"
console.log(fruits.length); // 3

// 添加元素
fruits.push("Mango");
console.log(fruits); // ["Apple", "Banana", "Orange", "Mango"]

// 数组方法
console.log(fruits.join(", ")); // "Apple, Banana, Orange, Mango"
let citrus = fruits.slice(1, 3);
console.log(citrus); // ["Banana", "Orange"]

console.log(typeof fruits); // "object"
console.log(Array.isArray(fruits)); // true

Function(函数)

函数在JavaScript中是一种特殊的对象,可以被调用执行。

javascript
// 函数声明
function add(a, b) {
return a + b;
}

// 函数表达式
const multiply = function(a, b) {
return a * b;
};

// 箭头函数(ES6)
const subtract = (a, b) => a - b;

console.log(add(5, 3)); // 8
console.log(multiply(5, 3)); // 15
console.log(subtract(5, 3)); // 2

console.log(typeof add); // "function"

类型检测

在JavaScript中,可以使用多种方式检测数据类型:

typeof运算符

javascript
console.log(typeof 42); // "number"
console.log(typeof "hello"); // "string"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object" (这是一个bug)
console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof function(){}); // "function"

instanceof运算符

instanceof运算符用于检测对象是否属于某个构造函数的实例。

javascript
let arr = [1, 2, 3];
console.log(arr instanceof Array); // true
console.log(arr instanceof Object); // true (因为数组也是对象)

let date = new Date();
console.log(date instanceof Date); // true

其他检测方法

javascript
// 检测数组
console.log(Array.isArray([1, 2, 3])); // true

// 检测NaN
console.log(isNaN(NaN)); // true

// 检测有限数字
console.log(isFinite(42)); // true
console.log(isFinite(Infinity)); // false

类型转换

JavaScript会自动进行类型转换(也称为类型强制)。此外,你也可以显式地进行类型转换。

自动类型转换

javascript
console.log("5" + 2); // "52" (数字转为字符串)
console.log("5" - 2); // 3 (字符串转为数字)
console.log(5 + true); // 6 (布尔值转为数字,true变为1)
console.log(5 + false); // 5 (false变为0)

显式类型转换

javascript
// 转为数字
console.log(Number("42")); // 42
console.log(parseInt("42px", 10)); // 42
console.log(parseFloat("3.14")); // 3.14

// 转为字符串
console.log(String(42)); // "42"
console.log((42).toString()); // "42"

// 转为布尔值
console.log(Boolean(0)); // false
console.log(Boolean("hello")); // true
console.log(Boolean("")); // false

实际应用案例

案例1:构建用户资料表单验证

javascript
function validateUserProfile(profile) {
// 检查必填字段是否存在且类型正确
if (typeof profile.name !== "string" || profile.name.trim() === "") {
return { valid: false, error: "姓名必须是非空字符串" };
}

if (typeof profile.age !== "number" || isNaN(profile.age)) {
return { valid: false, error: "年龄必须是数字" };
}

if (typeof profile.email !== "string" || !profile.email.includes("@")) {
return { valid: false, error: "邮箱格式不正确" };
}

if (!Array.isArray(profile.interests) || profile.interests.length === 0) {
return { valid: false, error: "兴趣爱好必须是非空数组" };
}

return { valid: true };
}

// 测试
const profile1 = {
name: "Alice",
age: 28,
email: "alice@example.com",
interests: ["coding", "hiking"]
};

const profile2 = {
name: "",
age: "twenty-eight", // 错误的数据类型
email: "alice-example.com", // 缺少@
interests: []
};

console.log(validateUserProfile(profile1)); // { valid: true }
console.log(validateUserProfile(profile2)); // { valid: false, error: "姓名必须是非空字符串" }

案例2:购物车金额计算

javascript
function calculateCartTotal(items) {
// 确保items是数组
if (!Array.isArray(items)) {
throw new TypeError("购物项必须是数组");
}

return items.reduce((total, item) => {
// 检查商品格式是否正确
if (typeof item !== "object" || item === null) {
throw new TypeError("购物项必须是对象");
}

if (typeof item.price !== "number" || isNaN(item.price)) {
throw new TypeError(`商品 ${item.name || "未知"} 的价格必须是数字`);
}

if (typeof item.quantity !== "number" || !Number.isInteger(item.quantity) || item.quantity <= 0) {
throw new TypeError(`商品 ${item.name || "未知"} 的数量必须是正整数`);
}

return total + (item.price * item.quantity);
}, 0);
}

// 测试
const cartItems = [
{ name: "笔记本电脑", price: 5999, quantity: 1 },
{ name: "鼠标", price: 99.5, quantity: 2 },
{ name: "键盘", price: 249, quantity: 1 }
];

console.log(`购物车总金额: ¥${calculateCartTotal(cartItems)}`); // 购物车总金额: ¥6447

数据类型的内存表示

基本数据类型和引用数据类型在内存中的存储方式不同:

  • 基本数据类型直接存储在栈内存中,占用空间小、大小固定,赋值时进行值复制。
  • 引用数据类型在堆内存中存储数据本身,在栈内存中存储数据的引用(地址),占用空间大、大小不固定,赋值时只复制引用。

总结

JavaScript的数据类型系统是它灵活性的重要组成部分。虽然JavaScript是动态类型语言,但了解每种数据类型的特点和用法,对于编写高质量的JavaScript代码至关重要:

  1. 基本数据类型(Number、String、Boolean、Null、Undefined、Symbol、BigInt)直接表示简单的值。
  2. 引用数据类型(Object及其衍生如Array、Function、Date等)用于表示更复杂的数据结构。
  3. JavaScript提供了多种方法来检测和转换不同的数据类型。
  4. 理解类型转换规则可以避免许多常见错误。

掌握JavaScript的数据类型不仅是编写代码的基础,也是理解JavaScript更高级概念(如闭包、原型链等)的前提。

练习题

为了巩固所学知识,尝试完成以下练习:

  1. 创建一个函数,判断传入的参数是否是一个对象(不包括null)。
  2. 编写一个函数,接受任意类型的参数,并返回其详细的类型信息(不只是使用typeof)。
  3. 创建一个函数,可以深度比较两个值是否相等,包括处理对象和数组。
  4. 实现一个简单的类型安全的求和函数,只有当所有参数都是数字时才进行加法运算。

更多学习资源

继续深入学习JavaScript,探索更多高级主题!