一、核心分类:两大阵营七种类型
基本类型(值传递):
类型 | 特性 | 示例 |
---|---|---|
Undefined |
未定义状态 | let a; |
Null |
空值引用 | let b = null; |
Boolean |
逻辑真/假 | true , false |
Number |
双精度浮点数 | 42 , 3.14 , NaN |
BigInt |
任意精度整数 | 9007199254740991n |
String |
不可变文本序列 | "Hello" |
Symbol |
唯一标识符(ES6新增) | Symbol('id') |
引用类型(址传递):
类型 | 特性 | 典型创建方式 |
---|---|---|
Object |
键值对集合 | {} , new Object() |
Array |
有序集合 | [] , new Array() |
Function |
可执行对象 | function(){} |
Date |
日期时间 | new Date() |
RegExp |
正则表达式 | new RegExp() |
Map/Set |
集合结构(ES6新增) | new Map() , new Set() |
二、关键特性深度解析
1. Number 的精度陷阱
javascript
javascript
复制
console.log(0.1 + 0.2 === 0.3); // false (0.30000000000000004)
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log(Number.MAX_VALUE); // 1.7976931348623157e+308
解决方案:
javascript
javascript
复制
// 精确计算
function safeAdd(a, b) {
return parseFloat((a + b).toFixed(10));
}
// 大整数处理
const bigNum = 9007199254740995n;
2. 类型自动转换规则
javascript
javascript
复制
console.log(8 * null); // 0 (null → 0)
console.log("5" - 3); // 2 (字符串转数字)
console.log("5" + 3); // "53" (数字转字符串)
console.log([] == ![]); // true (!! 避免此操作)
防御性编程:
scss
javascript
复制
// 严格相等:先比较类型再比较值
console.log("5" === 5); // false
// 类型明确转换
const num = Number(input);
if (isNaN(num)) handleError();
3. Symbol 的唯一性原理
ini
javascript
复制
const id1 = Symbol('id');
const id2 = Symbol('id');
console.log(id1 === id2); // false
// 全局注册
const globalSym = Symbol.for('global');
console.log(Symbol.keyFor(globalSym)); // "global"
实践应用:
javascript
javascript
复制
// 对象唯一属性
const user = {
[Symbol('internal')]: 'secret'
};
// 防止属性冲突
Array.prototype[Symbol.iterator]; // 内置迭代器
三、引用类型核心机制
1. 对象属性管理
javascript
javascript
复制
const obj = { name: 'Alice' };
// 属性描述符查看
console.log(Object.getOwnPropertyDescriptor(obj, 'name'));
/*
{
value: "Alice",
writable: true,
enumerable: true,
configurable: true
}
*/
// 冻结对象防止修改
Object.freeze(obj);
obj.name = 'Bob'; // 严格模式下报错
2. Map vs Object 场景对比
特性 | Map | Object |
---|---|---|
键类型 | 任意值 | String/Symbol |
顺序保障 | 插入顺序 | 不保证(除ES6后) |
迭代性能 | 直接可迭代 | 需获取keys |
原型链污染 | 无风险 | 可能受影响 |
最佳实践:
ini
javascript
复制
// 键名动态或非字符串
const userMap = new Map();
userMap.set(account, profile);
// 需要传统键值对
const config = { apiUrl: '...', timeout: 5000 };
3. 数组类型特性和方法
javascript
javascript
复制
// 类型不统一
const mixedArr = [1, 'text', { id: 1 }];
// 类数组转换
function sum() {
return [...arguments].reduce((s, v) => s + v, 0);
}
// 现代API(ES6+)
const points = [40, 100, 1, 5, 25];
points.find(x => x > 50); // 100
Array.from(new Set([1,2,2,3])); // 去重 [1,2,3]
四、类型检测的现代方法
1. 精准类型判断方案
scss
javascript
复制
function getType(value) {
return Object.prototype.toString.call(value)
.slice(8, -1)
.toLowerCase();
}
getType([]); // 'array'
getType(null); // 'null'
getType(/regex/); // 'regexp'
2. 安全类型检查指南
javascript
javascript
复制
// 检查undefined
typeof variable === 'undefined'
// 检查null(注意==特殊性)
variable === null
// 检查数组
Array.isArray(variable)
// 检查NaN
Number.isNaN(value)
// 类数组检查
function isArrayLike(obj) {
return obj != null &&
typeof obj[Symbol.iterator] === 'function';
}
五、内存管理核心机制
1. 栈内存 vs 堆内存
特性 | 栈内存 | 堆内存 |
---|---|---|
存储内容 | 基本类型、指针 | 引用类型 |
分配方式 | 自动分配固定大小 | 动态分配 |
访问速度 | 快 | 慢(需指针跳转) |
内存管理 | 函数结束自动释放 | GC垃圾回收处理 |
csharp
javascript
复制
// 栈示例
let age = 30; // 值直接存储
// 堆示例
let person = { name: 'John' }; // 对象地址存储
2. 经典内存泄露场景
javascript
javascript
复制
// 1. 意外的全局变量
function leak() {
leaked = '全局变量'; // 未声明变量 → window.leaked
}
// 2. DOM元素引用未清理
let elements = {
button: document.getElementById('button')
};
// 3. 闭包未释放
function createHeavyClosure() {
const bigData = new Array(1000000);
return () => bigData.length; // bigData无法回收
}
// 4. 定时器未清除
setInterval(() => {
// 持有外部作用域
}, 1000);
防御策略:
csharp
javascript
复制
// WeakMap避免内存泄漏
const wm = new WeakMap();
wm.set(element, { data: '...' });
element.remove(); // element被回收时关联数据自动清除
六、ECMAScript 新特性解读
1. 可选链操作符(?.)
ini
javascript
复制
// 防止深度访问报错
const city = user.addresses?.[0]?.city;
// 函数安全调用
api.getData?.();
2. 空值合并运算符(??)
arduino
javascript
复制
// 区分空值和假值
const size = input.size ?? 'default';
const count = 0;
console.log(count || 20); // 20
console.log(count ?? 20); // 0
3. Record & Tuple 提案
csharp
javascript
复制
// 不可变数据结构
const user = #{
id: 1,
name: "Alice"
};
const ids = #[1, 2, 3];
结语:数据类型最佳实践
- 变量初始化 :声明时明确初始值(避免
undefined
扩散)
ini
javascript
复制
let count = 0; // 优于 let count;
- 类型转换规范:
ini
javascript
复制
// 字符串转数字
const num = +"123";
// 或
const num = parseInt("123", 10);
- 引用类型比较:
javascript
javascript
复制
// 不要用 == 比较对象/数组
JSON.stringify(arr1) === JSON.stringify(arr2); // 深比较方案
- 内存敏感场景:
arduino
javascript
复制
// 大型数据使用TypedArray
const buffer = new ArrayBuffer(1024 * 1024); // 1MB内存块
- 类型防御代码:
javascript
javascript
复制
function safeAccess(obj) {
// 新语法支持
return obj?.prop ?? 'default';
// 兼容方案
if (obj && typeof obj === 'object') {
return obj.prop;
}
}
掌握数据类型细节是编写健壮JavaScript代码的基石。随着ECMAScript标准的持续演进,不断更新对类型系统的理解,将助你构建更可靠的应用系统。