JavaScript: JavaScript 数据类型
数据类型决定了数据能做什么操作——数字能加减,字符串能拼接,布尔能判断。搞清楚类型,才能避免 JS 最经典的那些坑。
1. JS 的数据类型
JavaScript 有 8 种数据类型,分为基本类型和引用类型两大阵营:
基本类型(7种):String、Number、BigInt、Boolean、Undefined、Null、Symbol
引用类型(1种):Object(数组、函数、日期等都是 Object 的子类型)
基本类型的数据存在栈内存中,赋值时拷贝值;引用类型的数据存在堆内存中,赋值时拷贝引用(地址)。这个区别后续课程会深入讲。
▶ 示例
JAVASCRIPT
// 本节代码示例
const message = "你好,世界!";
console.log(message);
这是最简单的示例,后续章节会详细解释。## 2. typeof 运算符
typeof 是检测数据类型的运算符,返回一个字符串:
| 值 | typeof 结果 |
|---|---|
"hello" |
"string" |
42 |
"number" |
9007199254740991n |
"bigint" |
true |
"boolean" |
undefined |
"undefined" |
null |
"object" (历史bug) |
{ } |
"object" |
function(){} |
"function" |
注意:typeof null 返回 "object"——这是 JS 诞生时的一个历史 bug,修不了了(改了会破坏老代码),记住就好。
3. 字符串和数字的陷阱
JS 中 + 运算符有两个用途:数字相加和字符串拼接。当 + 两边有字符串时,JS 会把另一个值也转成字符串来拼接:
"5" + 3变成"53"(字符串拼接,不是数学加法)5 + 3变成8(数学加法)"5" - 3变成2(减法没有拼接语义,自动转数字)
这是 JS 最经典的陷阱之一,新手必踩。解决方法:做数学运算前用 Number() 或 parseInt() 显式转换。
4. null vs undefined 的区别
这两个都表示"没有值",但含义不同:
- undefined:变量已声明但未赋值,或者访问不存在的属性——"还没给值"
- null:开发者主动赋值为空——"明确设为空"
打个比方:undefined 是新房还没搬家具,null 是你主动把家具搬走了。
▶ 示例:typeof 检测各种类型
HTML
📖 仅展示
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>JS 数据类型 - typeof</title>
<style>
body { font-family: "Microsoft YaHei", sans-serif; max-width: 600px; margin: 60px auto; }
table { width: 100%; border-collapse: collapse; margin: 16px 0; }
th, td { padding: 10px; text-align: left; border: 1px solid #ddd; }
th { background: #2196F3; color: #fff; }
button { margin-top: 12px; padding: 10px 24px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; color: #fff; background: #2196F3; }
#result { margin-top: 12px; padding: 16px; background: #f5f5f5; border-radius: 8px; font-family: Consolas, monospace; line-height: 1.8; white-space: pre; }
</style>
</head>
<body>
<h2>typeof 运算符</h2>
<button id="testBtn">运行 typeof 测试</button>
<div id="result">点击按钮查看 typeof 结果</div>
<script>
document.getElementById("testBtn").onclick = function() {
var a = "hello";
var b = 42;
var c = 9007199254740991n;
var d = true;
var e = undefined;
var f = null;
var g = {name: "张三"};
var h = [1, 2, 3];
var i = function(){};
var output = "";
output += 'typeof "hello" → "' + typeof a + '"\n';
output += "typeof 42 → \"" + typeof b + '"\n';
output += "typeof 9007199254740991n → \"" + typeof c + '"\n';
output += "typeof true → \"" + typeof d + '"\n';
output += "typeof undefined → \"" + typeof e + '"\n';
output += "typeof null → \"" + typeof f + '" ⚠️ 这是历史Bug!\n';
output += "typeof {} → \"" + typeof g + '"\n';
output += "typeof [] → \"" + typeof h + '" (数组也是object)\n';
output += 'typeof function → "' + typeof i + '"';
document.getElementById("result").textContent = output;
};
</script>
</body>
</html>
▶ 示例:字符串与数字的陷阱
HTML
📖 仅展示
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>JS 数据类型 - 字符串与数字陷阱</title>
<style>
body { font-family: "Microsoft YaHei", sans-serif; max-width: 550px; margin: 60px auto; }
.trap { background: #fff3e0; padding: 12px; border-radius: 8px; color: #E65100; border-left: 4px solid #FF9800; margin: 12px 0; }
.safe { background: #e8f5e9; padding: 12px; border-radius: 8px; color: #2E7D32; border-left: 4px solid #4CAF50; margin: 12px 0; }
.row { display: flex; justify-content: space-between; padding: 10px 16px; border-bottom: 1px solid #eee; font-family: Consolas, monospace; }
.row:last-child { border-bottom: none; }
.result-box { background: #f5f5f5; border-radius: 8px; margin: 12px 0; overflow: hidden; }
.label { color: #666; }
.value { font-weight: bold; }
.bad { color: #f44336; }
.good { color: #4CAF50; }
button { margin-top: 12px; padding: 10px 24px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; color: #fff; background: #e91e63; }
</style>
</head>
<body>
<h2>字符串 + 数字的陷阱</h2>
<p class="trap">⚠️ 当 + 两边有字符串时,JS 会拼接而非相加!"5"+3 得 "53" 而非 8</p>
<button id="trapBtn">运行陷阱演示</button>
<div class="result-box" id="trapResult">
<div class="row"><span class="label">"5" + 3 =</span><span class="value" id="r1">?</span></div>
<div class="row"><span class="label">5 + 3 =</span><span class="value" id="r2">?</span></div>
<div class="row"><span class="label">"5" - 3 =</span><span class="value" id="r3">?</span></div>
<div class="row"><span class="label">"5" * 3 =</span><span class="value" id="r4">?</span></div>
</div>
<p class="safe">✅ 解决方法:用 Number() 显式转换后再运算</p>
<button id="safeBtn" style="background:#4CAF50;">运行安全写法</button>
<div class="result-box" id="safeResult">
<div class="row"><span class="label">Number("5") + 3 =</span><span class="value" id="s1">?</span></div>
</div>
<script>
document.getElementById("trapBtn").onclick = function() {
var r1 = "5" + 3;
var r2 = 5 + 3;
var r3 = "5" - 3;
var r4 = "5" * 3;
document.getElementById("r1").textContent = '"' + r1 + '"';
document.getElementById("r1").className = "value bad";
document.getElementById("r2").textContent = r2;
document.getElementById("r2").className = "value good";
document.getElementById("r3").textContent = r3;
document.getElementById("r3").className = "value good";
document.getElementById("r4").textContent = r4;
document.getElementById("r4").className = "value good";
};
document.getElementById("safeBtn").onclick = function() {
var s1 = Number("5") + 3;
document.getElementById("s1").textContent = s1;
document.getElementById("s1").className = "value good";
};
</script>
</body>
</html>
▶ 示例:null 与 undefined 的区别
HTML
📖 仅展示
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>JS 数据类型 - null vs undefined</title>
<style>
body { font-family: "Microsoft YaHei", sans-serif; max-width: 550px; margin: 60px auto; }
.card { padding: 16px; border-radius: 8px; margin: 12px 0; }
.undef { background: #e3f2fd; border-left: 4px solid #2196F3; }
.nul { background: #f3e5f5; border-left: 4px solid #9C27B0; }
.result { background: #f5f5f5; padding: 16px; border-radius: 8px; font-family: Consolas, monospace; line-height: 1.8; white-space: pre; margin: 12px 0; }
button { padding: 10px 24px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; color: #fff; background: #9C27B0; margin: 6px; }
</style>
</head>
<body>
<h2>null vs undefined</h2>
<div class="card undef">
<strong>undefined</strong>:变量声明了但没赋值,或访问不存在的属性<br>
含义:"还没给值" —— 像新房还没搬家具
</div>
<div class="card nul">
<strong>null</strong>:开发者主动赋值为空<br>
含义:"明确设为空" —— 你主动把家具搬走了
</div>
<button id="testBtn">运行对比测试</button>
<div class="result" id="output">点击按钮查看结果</div>
<script>
document.getElementById("testBtn").onclick = function() {
var a;
var b = null;
var c = {name: "张三"};
var output = "";
output += "=== undefined 情况 ===\n";
output += "var a; → a = " + a + " (undefined)\n";
output += "typeof a → \"" + typeof a + "\"\n";
output += "c.age → " + c.age + " (不存在的属性也是undefined)\n\n";
output += "=== null 情况 ===\n";
output += "var b = null; → b = " + b + " (null)\n";
output += "typeof b → \"" + typeof b + "\" ⚠️ 历史Bug\n\n";
output += "=== 区别对比 ===\n";
output += "null == undefined → " + (null == undefined) + " (宽松相等)\n";
output += "null === undefined → " + (null === undefined) + " (严格不等)\n";
output += "typeof null → \"object\" (bug)\n";
output += "typeof undefined → \"undefined\" (正确)\n\n";
output += "结论:null === undefined 为 false\n";
output += "它们含义不同,严格比较时不是同一个值";
document.getElementById("output").textContent = output;
};
</script>
</body>
</html>
▶ 示例:各种数据类型一览
HTML
📖 仅展示
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>JS 数据类型 - 完整一览</title>
<style>
body { font-family: "Microsoft YaHei", sans-serif; max-width: 600px; margin: 60px auto; }
.type-card { display: inline-block; width: 120px; padding: 16px; margin: 6px; border-radius: 10px; text-align: center; color: #fff; cursor: pointer; transition: transform 0.2s; }
.type-card:hover { transform: scale(1.08); }
.type-card h3 { margin: 0 0 4px; font-size: 14px; opacity: 0.9; }
.type-card p { margin: 0; font-size: 12px; font-family: Consolas, monospace; }
.string { background: #4CAF50; }
.number { background: #2196F3; }
.bigint { background: #e91e63; }
.boolean { background: #FF9800; }
.undef { background: #9E9E9E; }
.nul { background: #795548; }
.symbol { background: #00BCD4; }
.object { background: #9C27B0; }
#detail { margin-top: 20px; padding: 20px; background: #f5f5f5; border-radius: 8px; font-size: 16px; line-height: 1.8; display: none; }
</style>
</head>
<body>
<h2>JS 8 种数据类型</h2>
<div class="type-card string" onclick="showDetail('string')"><h3>String</h3><p>"hello"</p></div>
<div class="type-card number" onclick="showDetail('number')"><h3>Number</h3><p>42</p></div>
<div class="type-card bigint" onclick="showDetail('bigint')"><h3>BigInt</h3><p>900n</p></div>
<div class="type-card boolean" onclick="showDetail('boolean')"><h3>Boolean</h3><p>true</p></div>
<div class="type-card undef" onclick="showDetail('undefined')"><h3>Undefined</h3><p>undefined</p></div>
<div class="type-card nul" onclick="showDetail('null')"><h3>Null</h3><p>null</p></div>
<div class="type-card symbol" onclick="showDetail('symbol')"><h3>Symbol</h3><p>Symbol()</p></div>
<div class="type-card object" onclick="showDetail('object')"><h3>Object</h3><p>{key:"val"}</p></div>
<div id="detail"></div>
<script>
function showDetail(type) {
var detailEl = document.getElementById("detail");
detailEl.style.display = "block";
var info = {
"string": "String(字符串)\n用引号包裹的文本:\"hello\"、'world'\ntypeof → \"string\"\n可以用 + 拼接字符串",
"number": "Number(数字)\n整数和小数:42、3.14、-7\n特殊值:Infinity、-Infinity、NaN\ntypeof → \"number\"",
"bigint": "BigInt(大整数)\n表示超过 Number 安全范围的整数\n写法:数字后加 n,如 9007199254740991n\ntypeof → \"bigint\"",
"boolean": "Boolean(布尔值)\n只有两个值:true 和 false\n常用于条件判断\ntypeof → \"boolean\"",
"undefined": "Undefined(未定义)\n变量声明但未赋值时的默认值\ntypeof → \"undefined\"\n表示\"还没有值\"",
"null": "Null(空值)\n开发者主动赋值表示\"空\"\ntypeof → \"object\" (历史Bug!)\nnull === undefined 为 false",
"symbol": "Symbol(符号)\nES6 新增,创建唯一标识符\n每个 Symbol() 都不相同\ntypeof → \"symbol\"\n常用于对象属性键",
"object": "Object(对象)\n引用类型,存储键值对集合\n数组 []、函数、日期都是 object\ntypeof → \"object\""
};
detailEl.textContent = info[type];
}
</script>
</body>
</html>
❓ 常见问题
Q 为什么
typeof null 是 "object"?A 这是 JS 第一版的历史 bug。当时 JS 用低位标识类型,
null 的低位全是 0,和 object 的标识一样,就误判了。后来想修,但改了会破坏大量现有代码,只好将错就错——就像一栋楼的地基歪了,住的人太多没法推倒重来。Q 怎么判断一个值是数组而不是普通对象?
A
typeof 对数组和对象都返回 "object",区分不了。正确方法是用 Array.isArray(),比如 Array.isArray([1,2]) 返回 true,Array.isArray({}) 返回 false。Q NaN 是什么类型?
A
NaN(Not a Number)虽然名字叫"不是数字",但 typeof NaN 返回 "number"。更离谱的是 NaN === NaN 返回 false——自己都不等于自己。判断 NaN 要用 isNaN() 或 Number.isNaN()。📖 小节
- JS 有 8 种数据类型:7 种基本类型 + 1 种引用类型 Object
typeof运算符检测类型,但typeof null返回"object"是历史遗留 bug+遇到字符串会拼接而非相加,"5" + 3得"53"不是8null表示"明确设为空",undefined表示"还没给值",二者严格不相等- 做数学运算前用
Number()或parseInt()显式转换,避免隐式转换的坑 - 数组
[]的 typeof 也是"object",要区分数组和对象需要其他方法
📝 作业
- 基础题:声明 6 个变量分别对应 6 种基本类型(String、Number、Boolean、Undefined、Null、Object),用
typeof逐一检测并在页面上显示结果。 - 进阶题:创建一个页面,包含一个输入框,用户输入任意值后,JS 判断其类型(用 typeof)并显示在页面上。尝试输入数字、字符串、true、null 等,观察 typeof 的返回结果。
- 挑战题:创建一个"类型陷阱测试"页面,列出 5 道选择题测试用户对类型转换的理解,比如
"1" + 2等于什么、null == undefined是 true 还是 false 等,用户点击选项后显示对错和解释。