JavaScript的数据类型分为两大类:原始类型(Primitive Types)和引用类型(Reference Types)。
原始类型存储的是实际的值,共有7种:
// 1. Number - 数字
let age = 25;
let price = 99.99;
let temperature = -10;
// 2. String - 字符串
let name = "东巴文";
let greeting = '你好';
let template = `欢迎`;
// 3. Boolean - 布尔值
let isActive = true;
let isLoggedIn = false;
// 4. Undefined - 未定义
let notDefined;
console.log(notDefined); // undefined
// 5. Null - 空值
let empty = null;
// 6. Symbol - 符号(ES6)
let id = Symbol("unique");
// 7. BigInt - 大整数(ES2020)
let bigNumber = 9007199254740991n;
引用类型存储的是指向内存位置的引用:
// Object - 对象
let user = {
name: "东巴文",
age: 1
};
// Array - 数组
let numbers = [1, 2, 3, 4, 5];
// Function - 函数
function greet() {
return "Hello";
}
// Date - 日期
let now = new Date();
// RegExp - 正则表达式
let pattern = /\d+/;
// Map、Set 等
let map = new Map();
let set = new Set();
| 特性 | 原始类型 | 引用类型 | 东巴文比喻 |
|---|---|---|---|
| 存储方式 | 存储实际值 | 存储引用地址 | 原始类型是值,引用类型是地址 |
| 存储位置 | 栈内存 | 堆内存 | 栈快,堆大 |
| 复制行为 | 复制值 | 复制引用 | 原始类型独立,引用类型共享 |
| 比较 | 比较值 | 比较引用地址 | 原始类型看内容,引用类型看地址 |
| 可变性 | 不可变 | 可变 | 原始类型不能改,引用类型可以改 |
// 原始类型 - 值复制
let a = 10;
let b = a; // 复制值
b = 20;
console.log(a); // 10(a不受影响)
// 引用类型 - 引用复制
let obj1 = { name: "东巴文" };
let obj2 = obj1; // 复制引用
obj2.name = "新名字";
console.log(obj1.name); // "新名字"(obj1也变了)
东巴文图解:
原始类型:
变量名 栈内存
a → 10
b → 20(复制后独立)
引用类型:
变量名 栈内存 堆内存
obj1 → 引用地址 ──────→ { name: "新名字" }
obj2 → 引用地址 ──────→ (指向同一对象)
// 原始类型 - 比较值
console.log(10 === 10); // true
console.log("东巴文" === "东巴文"); // true
// 引用类型 - 比较引用地址
let obj1 = { name: "东巴文" };
let obj2 = { name: "东巴文" };
console.log(obj1 === obj2); // false(不同对象)
let obj3 = obj1;
console.log(obj1 === obj3); // true(同一引用)
typeof操作符用于检测数据类型,返回一个字符串。
typeof 42; // "number"
typeof 3.14; // "number"
typeof "东巴文"; // "string"
typeof true; // "boolean"
typeof undefined; // "undefined"
typeof null; // "object"(历史遗留问题)
typeof Symbol(); // "symbol"
typeof 10n; // "bigint"
typeof {}; // "object"
typeof []; // "object"
typeof function(){}; // "function"
typeof null; // "object"
| 类型 | 返回值 | 东巴文备注 |
|---|---|---|
| Number | "number" | 包括NaN和Infinity |
| String | "string" | - |
| Boolean | "boolean" | - |
| Undefined | "undefined" | - |
| Null | "object" | ⚠️ 历史遗留问题 |
| Symbol | "symbol" | ES6新增 |
| BigInt | "bigint" | ES2020新增 |
| Object | "object" | 包括数组、正则等 |
| Function | "function" | 函数是特殊的对象 |
// 1. null的特殊情况
typeof null; // "object"(这是JavaScript的bug)
// 正确检测null
function isNull(value) {
return value === null;
}
// 2. 数组的检测
typeof []; // "object"
// 正确检测数组
Array.isArray([]); // true
[] instanceof Array; // true
// 3. NaN的检测
typeof NaN; // "number"
// 正确检测NaN
Number.isNaN(NaN); // true
// 4. 未声明变量的检测
// console.log(notDefined); // ReferenceError
typeof notDefined; // "undefined"(不会报错)
function getType(value) {
if (value === null) return "null";
if (Array.isArray(value)) return "array";
if (value instanceof Date) return "date";
if (value instanceof RegExp) return "regexp";
return typeof value;
}
console.log(getType(null)); // "null"
console.log(getType([])); // "array"
console.log(getType(new Date())); // "date"
console.log(getType(42)); // "number"
适用于原始类型(除null外):
function isNumber(value) {
return typeof value === "number" && !Number.isNaN(value);
}
function isString(value) {
return typeof value === "string";
}
function isBoolean(value) {
return typeof value === "boolean";
}
function isUndefined(value) {
return typeof value === "undefined";
}
function isSymbol(value) {
return typeof value === "symbol";
}
function isBigInt(value) {
return typeof value === "bigint";
}
适用于引用类型,检测原型链:
function isObject(value) {
return value !== null && typeof value === "object";
}
function isArray(value) {
return Array.isArray(value);
}
function isFunction(value) {
return typeof value === "function";
}
function isDate(value) {
return value instanceof Date;
}
function isRegExp(value) {
return value instanceof RegExp;
}
function isMap(value) {
return value instanceof Map;
}
function isSet(value) {
return value instanceof Set;
}
最准确的类型检测方法:
function getExactType(value) {
return Object.prototype.toString.call(value).slice(8, -1);
}
console.log(getExactType(null)); // "Null"
console.log(getExactType(undefined)); // "Undefined"
console.log(getExactType(42)); // "Number"
console.log(getExactType("东巴文")); // "String"
console.log(getExactType(true)); // "Boolean"
console.log(getExactType([])); // "Array"
console.log(getExactType({})); // "Object"
console.log(getExactType(function(){})); // "Function"
console.log(getExactType(new Date())); // "Date"
console.log(getExactType(/regex/)); // "RegExp"
console.log(getExactType(new Map())); // "Map"
console.log(getExactType(new Set())); // "Set"
console.log(getExactType(Symbol())); // "Symbol"
console.log(getExactType(10n)); // "BigInt"
function typeOf(value) {
const type = Object.prototype.toString.call(value).slice(8, -1);
const typeMap = {
'Number': 'number',
'String': 'string',
'Boolean': 'boolean',
'Undefined': 'undefined',
'Null': 'null',
'Symbol': 'symbol',
'BigInt': 'bigint',
'Object': 'object',
'Array': 'array',
'Function': 'function',
'Date': 'date',
'RegExp': 'regexp',
'Map': 'map',
'Set': 'set',
'WeakMap': 'weakmap',
'WeakSet': 'weakset',
'Promise': 'promise',
'Error': 'error'
};
return typeMap[type] ? typeMap[type] : type.toLowerCase();
}
console.log(typeOf(null)); // "null"
console.log(typeOf([])); // "array"
console.log(typeOf({})); // "object"
console.log(typeOf(42)); // "number"
console.log(typeOf(new Map())); // "map"
JavaScript是一种弱类型语言,支持隐式类型转换,也支持显式类型转换。
JavaScript在某些操作中会自动进行类型转换:
// 字符串拼接
console.log(1 + "2"); // "12"
console.log("东巴文" + 2024); // "东巴文2024"
// 算术运算
console.log("5" - 3); // 2
console.log("5" * "2"); // 10
console.log("10" / 2); // 5
// 比较运算
console.log(5 == "5"); // true(隐式转换)
console.log(5 === "5"); // false(严格相等)
// 布尔转换
if ("非空字符串") {
console.log("执行"); // 执行
}
// 逻辑运算
console.log(1 || 2); // 1
console.log(0 && 1); // 0
手动进行类型转换更加清晰可控:
// 转换为字符串
String(123); // "123"
(123).toString(); // "123"
123 + ""; // "123"
// 转换为数字
Number("123"); // 123
parseInt("123"); // 123
parseFloat("3.14"); // 3.14
+"123"; // 123
// 转换为布尔值
Boolean(1); // true
!!1; // true
Boolean(""); // false
!!""; // false
// 转换为对象
Object(123); // Number {123}
Object("东巴文"); // String {"东巴文"}
| 原始值 | 转换结果 | 东巴文说明 |
|---|---|---|
| undefined | "undefined" | - |
| null | "null" | - |
| true | "true" | - |
| false | "false" | - |
| 123 | "123" | - |
| NaN | "NaN" | - |
| Infinity | "Infinity" | - |
| [] | "" | 空数组 |
| [1, 2] | "1,2" | 数组元素用逗号连接 |
| {} | "[object Object]" | 对象 |
| 原始值 | 转换结果 | 东巴文说明 |
|---|---|---|
| undefined | NaN | - |
| null | 0 | - |
| true | 1 | - |
| false | 0 | - |
| "123" | 123 | 纯数字字符串 |
| "3.14" | 3.14 | 浮点数 |
| "" | 0 | 空字符串 |
| "东巴文" | NaN | 非数字字符串 |
| [] | 0 | 空数组 |
| [5] | 5 | 单元素数组 |
| [1, 2] | NaN | 多元素数组 |
| {} | NaN | 对象 |
| 原始值 | 转换结果 | 东巴文说明 |
|---|---|---|
| undefined | false | 假值 |
| null | false | 假值 |
| 0 | false | 假值 |
| -0 | false | 假值 |
| NaN | false | 假值 |
| "" | false | 假值(空字符串) |
| false | false | 假值 |
| 其他 | true | 真值 |
JavaScript中只有以下值会被转换为false:
const falsyValues = [
false,
0,
-0,
0n,
"", // 空字符串
null,
undefined,
NaN
];
falsyValues.forEach(value => {
console.log(Boolean(value)); // 全部输出 false
});
// 注意:这些值是真值(Truthy)
console.log(Boolean([])); // true(空数组)
console.log(Boolean({})); // true(空对象)
console.log(Boolean(" ")); // true(空格字符串)
console.log(Boolean("false")); // true(字符串"false")
东巴文提醒:空数组[]和空对象{}是真值,这在条件判断时要特别注意。
console.log(1 + 2 + "3"); // "33"
console.log("1" + 2 + 3); // "123"
console.log(1 + "2" + 3); // "123"
// 解析:
// 1 + 2 = 3, 然后 3 + "3" = "33"
// "1" + 2 = "12", 然后 "12" + 3 = "123"
console.log([] == false); // true
console.log([] == ![]); // true
console.log({} == !{}); // false
// 解析:
// [] 转换为 "" 再转换为 0
// false 转换为 0
// 所以 [] == false 为 true
// 推荐:使用严格相等 ===
console.log([] === false); // false
console.log([] === ![]); // false
const obj = {
valueOf() {
return 42;
},
toString() {
return "东巴文";
}
};
console.log(obj + 8); // 50(调用valueOf)
console.log(String(obj)); // "东巴文"(调用toString)
// 没有valueOf时
const obj2 = {
toString() {
return "东巴文";
}
};
console.log(obj2 + "你好"); // "东巴文你好"
东巴文建议:了解类型转换规则,但尽量使用显式转换,避免隐式转换带来的意外。
了解了数据类型概述后,让我们深入学习:
东巴文(db-w.cn) - 让编程学习更简单
🔍 东巴文寄语:理解数据类型是JavaScript编程的基础。掌握原始类型和引用类型的区别,能帮助你避免很多常见的错误。在 db-w.cn,我们帮你建立扎实的知识体系!