数据类型(Data Types)
JavaScript 中的数据类型:原始类型与对象类型的使用和底层原理
📖 入门:基础使用
1. 数据类型分类
JavaScript 中的数据类型分为两大类:
1.1 原始类型(Primitive Types)
7 种原始类型:
number— 数字string— 字符串boolean— 布尔值undefined— 未定义null— 空值symbol— 符号(ES6)bigint— 大整数(ES2020)
特点:
- ✅ 值不可变(immutable)
- ✅ 按值传递
- ✅ 存储在栈内存中
示例:
let num = 42; // number
let str = "Hello"; // string
let bool = true; // boolean
let undef = undefined; // undefined
let nul = null; // null
let sym = Symbol("id"); // symbol
let big = 9007199254740991n; // bigint1.2 对象类型(Object Types)
对象类型:
Object— 普通对象Array— 数组Function— 函数Date— 日期RegExp— 正则表达式- 等等…
特点:
- ✅ 值可变(mutable)
- ✅ 按引用传递
- ✅ 存储在堆内存中
示例:
let obj = { name: "Alice" }; // Object
let arr = [1, 2, 3]; // Array
let func = function() {}; // Function2. 类型判断
2.1 typeof 运算符
语法:
typeof value示例:
typeof 42; // "number"
typeof "hello"; // "string"
typeof true; // "boolean"
typeof undefined; // "undefined"
typeof null; // "object" ⚠️(历史遗留问题)
typeof {}; // "object"
typeof []; // "object"
typeof function(){}; // "function"注意:
typeof null返回"object"(这是 JavaScript 的历史遗留问题)typeof无法区分数组和对象
2.2 instanceof 运算符
语法:
value instanceof Constructor示例:
[] instanceof Array; // true
[] instanceof Object; // true(数组也是对象)
{} instanceof Object; // true
new Date() instanceof Date; // true2.3 Object.prototype.toString()
更准确的类型判断:
Object.prototype.toString.call(42); // "[object Number]"
Object.prototype.toString.call("hello"); // "[object String]"
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call([]); // "[object Array]"
Object.prototype.toString.call({}); // "[object Object]"3. 类型转换
3.1 显式类型转换
转换为字符串:
String(123); // "123"
(123).toString(); // "123"
String(null); // "null"
String(undefined); // "undefined"转换为数字:
Number("123"); // 123
Number(""); // 0
Number("abc"); // NaN
parseInt("123"); // 123
parseFloat("12.3"); // 12.3转换为布尔值:
Boolean(1); // true
Boolean(0); // false
Boolean(""); // false
Boolean("hello"); // true
Boolean(null); // false
Boolean(undefined); // false3.2 隐式类型转换
字符串拼接:
"Hello" + 123; // "Hello123"
123 + "456"; // "123456"数学运算:
"123" - 1; // 122(字符串转数字)
"123" * 2; // 246
"123" / 1; // 123布尔值转换:
if (1) { } // 1 转换为 true
if ("") { } // "" 转换为 false
if (0) { } // 0 转换为 false🚀 提高:底层原理
1. 内存模型
1.1 栈内存(Stack)
原始类型存储:
- 原始类型的值直接存储在栈内存中
- 访问速度快
- 内存占用小
示例:
let a = 10;
let b = a; // 复制值
b = 20;
console.log(a); // 10(a 的值不变)内存布局:
栈内存
├── a: 10
└── b: 20(独立的值)
1.2 堆内存(Heap)
对象类型存储:
- 对象存储在堆内存中
- 变量存储的是对象的引用(地址)
- 访问速度相对较慢
- 内存占用较大
示例:
let obj1 = { name: "Alice" };
let obj2 = obj1; // 复制引用
obj2.name = "Bob";
console.log(obj1.name); // "Bob"(obj1 和 obj2 指向同一个对象)内存布局:
栈内存 堆内存
├── obj1 ────┐
└── obj2 ────┘ └── { name: "Bob" }
2. 值传递 vs 引用传递
2.1 原始类型:值传递
原理:
- 传递的是值的副本
- 修改不会影响原变量
示例:
function change(x) {
x = 100; // 修改的是副本
}
let num = 10;
change(num);
console.log(num); // 10(原值不变)2.2 对象类型:引用传递
原理:
- 传递的是对象的引用(地址)
- 修改会影响原对象
示例:
function change(obj) {
obj.name = "Bob"; // 修改的是原对象
}
let person = { name: "Alice" };
change(person);
console.log(person.name); // "Bob"(原对象被修改)3. 类型转换机制
3.1 抽象操作(Abstract Operations)
JavaScript 引擎使用抽象操作进行类型转换:
ToPrimitive:
- 将值转换为原始类型
- 优先级:
valueOf()→toString()
ToNumber:
- 将值转换为数字
- 规则复杂,涉及多种情况
ToString:
- 将值转换为字符串
ToBoolean:
- 将值转换为布尔值
- 遵循”假值”(falsy)规则
3.2 类型转换规则
原始类型转换:
// 转换为数字
Number("123"); // 123
Number(""); // 0
Number("abc"); // NaN
Number(true); // 1
Number(false); // 0
Number(null); // 0
Number(undefined); // NaN
// 转换为字符串
String(123); // "123"
String(true); // "true"
String(null); // "null"
String(undefined); // "undefined"
// 转换为布尔值
Boolean(0); // false
Boolean(""); // false
Boolean(null); // false
Boolean(undefined);// false
Boolean(NaN); // false
// 其他值都是 true对象类型转换:
// 对象转原始类型
let obj = {
valueOf() { return 42; },
toString() { return "Object"; }
};
Number(obj); // 42(先调用 valueOf)
String(obj); // "Object"(先调用 toString)4. 假值(Falsy Values)
JavaScript 中的假值:
false0""(空字符串)nullundefinedNaN
示例:
if (!value) {
// value 是假值时执行
}
// 真值(Truthy)检查
if (value) {
// value 是真值时执行
}5. null 和 undefined 的区别
undefined:
- 变量声明但未赋值
- 函数参数未提供
- 对象属性不存在
- 函数没有返回值
null:
- 表示”空值”的明确赋值
- 是一个对象引用
- 需要显式赋值
示例:
let a; // undefined(未赋值)
let b = null; // null(明确赋值)
// typeof 的区别
typeof undefined; // "undefined"
typeof null; // "object"(历史遗留)
// 相等性
undefined == null; // true(相等)
undefined === null; // false(不全等)📝 最佳实践
- 使用严格相等:使用
===而不是==避免类型转换 - 明确类型判断:使用
Object.prototype.toString()进行准确的类型判断 - 避免隐式转换:明确进行类型转换,避免依赖隐式转换
- 理解假值:清楚哪些值是假值,避免误判
🔗 相关链接
- 变量声明 — 变量的声明和使用
- 内置对象与 API — JavaScript 内置对象
- ECMAScript 类型规范