类型与变量
let/const、基本类型、typeof。
类型与变量
这一课你将能做到
- 用
const / let 声明变量,并说出二者差别与默认该选哪个
- 认出常见类型:数字、字符串、布尔、
null、undefined,并用 typeof 做一次探测
- 解释对象/数组变量里装的是「值」还是「引用」的直觉,能预测「改 B 是否动到 A」
为什么要学
程序要记住东西:用户名、是否登录、列表有几项。
变量就是「贴了名字的盒子」。盒子里可以是数字、文字等不同类型。
类型搞不清,后面会出现:明明有内容却判断失败、改 A 却动了 B、输入框的 "10" 和数字 10 搅在一起。
这一课把「起名字」和「盒子里是什么」先稳住,后面运算符、函数才好学。
先建立图像
const name = "ada"; // 盒子名叫 name,里面是文字 ada;不能换绑别的值
let count = 0; // 盒子名叫 count,里面是数字 0,允许换成别的数字
| 关键字 | 人话 | 典型用法 |
|---|
const | 这个名字不能指向别的东西 | 默认首选 |
let | 允许重新赋值 | 计数器、会变的状态 |
var | 老写法,作用域怪异 | 新代码尽量别用 |
注意:const 不是「盒子里永远不能改」。
对对象来说,不能换绑另一个对象,但对象内部属性常常仍能改——对象课会展开。
基本类型(number/string/boolean…)
变量里直接是「那份值」的感觉
对象 / 数组
变量里更像「指向那份数据的地址」
两个变量可指向同一份 → 改一份两边都看见
跟着做
步骤 1:在控制台声明并观察报错
打开浏览器控制台,输入:
// 默认用 const:名字固定指向这份数据
const site = "CodeRoadMap";
// 会变的计数器用 let
let clicks = 0;
clicks = clicks + 1;
console.log(site, clicks); // 应看到 CodeRoadMap 和 1
再试(预期会报错):
site = "其他"; // const 不能重新赋值 → TypeError
你应看到报错。这说明 const 在「换绑」这件事上是硬限制。
步骤 2:用 typeof 看类型
typeof 1; // "number"
typeof "1"; // "string" —— 带引号是文字,不是数字
typeof true; // "boolean"
typeof undefined; // "undefined"
typeof null; // "object" ← 历史坑,记住即可,别据此判断 null
typeof {}; // "object"
typeof []; // "object" —— 数组也是对象的一种
typeof function () {}; // "function"
人话对照:
- number:数字(含小数;也有特殊值
NaN、Infinity)
- string:字符串(文字)
boolean:真/假,只有 true / falseundefined:还没赋值时的「空」null:你故意表示「空 / 没有对象」步骤 3:字符串的三种写法
const a = "双引号";
const b = '单引号';
const name = "同学";
// 模板字符串:反引号,可插入表达式
const c = `你好,${name},分数是 ${10 + 2}`;
console.log(c); // 你好,同学,分数是 12
你应看到拼接后的整句。后续 UI 文案常用模板字符串,比一堆 + 好读。
步骤 4:写进页面,看见变量如何驱动界面
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>变量</title>
</head>
<body>
<p id="msg"></p>
<button type="button" id="plus">分数 +1</button>
<script>
const userName = "同学"; // 不变的名字
let score = 0; // 会变的分数
const msg = document.getElementById("msg");
function render() {
// 每次把变量「画」到页面上
msg.textContent = `${userName} 的分数是 ${score}`;
}
render();
document.getElementById("plus").addEventListener("click", function () {
score = score + 1; // 改数据
render(); // 再刷新显示
});
</script>
</body>
</html>
点击按钮:分数应递增。这就是「状态在变量里,界面跟着变量走」的雏形。
步骤 5:感受「引用」直觉(改 B 动 A)
// 基本类型:互不影响
let x = 1;
let y = x;
y = 2;
console.log(x, y); // 1 2
// 对象:两个名字指向同一份
const a = { city: "天津" };
const b = a; // 没有复制一份新对象,只是多了个别名
b.city = "北京";
console.log(a.city); // "北京" —— a 也被改了
你应看到对象情况下两边一起变。数组同理。后面会学浅拷贝;现在先建立「别以为赋值一定是复印」的警觉。
步骤 6:未声明变量与严格模式意识
// 不要这样:漏写 let/const,容易制造隐式全局(严格模式会直接报错)
// score = 1;
// 正确:先声明再使用
let total = 0;
total = 1;
console.log(total);
在现代模块/"use strict" 下,未声明赋值会失败——这是好事。养成「先声明」的习惯。
讲清楚要点
- 因为多数名字不该被换绑,所以默认写
const,真要变再用 let。
- 因为字符串是带引号的文字,所以
"10" 与 10 类型不同,后面比较/运算前要分清。
- 因为
typeof null === "object" 是历史遗留,所以判断空值请显式写 value === null 或统一空值策略。
- 因为对象/数组变量像「地址」,所以
const obj = {} 仍可改属性;const 锁的是绑定,不是深度冻结。
- 因为命名是给未来的自己看的,所以用可读驼峰名(
userName),避免 x1、a。
- 因为界面应反映数据,所以先改变量,再更新 DOM(步骤 4 的
render 模式)。
你可能会懵的地方
-
null 和 undefined 有啥区别?
undefined 常是「还没给 / 没这个属性」;null 常是「明确没有」。
判断时都要小心,别混用语义。
-
为什么 const 数组还能 push?
const 锁的是「变量指向谁」,不是深入冻结内容。push 改的是数组内部,没有换绑。
-
未写 let/const 直接赋值?
严格模式/模块里会报错;非严格可能制造全局变量,极难查。永远显式声明。
-
NaN 算 number 吗?
算。typeof NaN === "number"。它表示「不是合法数字运算结果」。用 Number.isNaN 判断。
错法对照
| 错法 | 问题 | 正解 |
|---|
全用 var | 作用域提升怪异、难维护 | const / let |
| 数字和数字字符串分不清 | "1"+2 变 "12" | 看清引号;需要时 Number(...) |
| 变量名乱起 | 一周后自己看不懂 | 有意义的驼峰名 |
以为 const 对象完全不可变 | 改属性时困惑 | 分清「换绑」与「改内部」 |
| 两个对象变量当复印件 | 改 B 动 A | 需要独立副本时再学拷贝 |
自测三问
- 什么时候用
const,什么时候用 let?默认选哪个?
"10" 和 10 是同一类型吗?typeof 各是什么?
typeof null 的结果是什么?为什么说它是坑?
小结一句话
变量是带名字的盒子;默认 const,会变才用 let;先分清数字、文字、真假和空值,并对对象/数组的「共享引用」保持警觉。
延伸