写程序本质上就是在”处理数据”:用户名、商品价格、是否登录、购物车里几件商品……这些数据不能凭空出现,得有个地方先存着、后面再取用。存数据的地方,就叫变量。
你可以把变量想象成一个贴了标签的盒子:你往里放东西(赋值),之后凭标签(变量名)就能把东西取出来用。比如 age 这个盒子,今天放 18,明天可以换成 19,但盒子还是那个盒子。程序之所以能”记住”东西、能随着用户操作变化,靠的全是变量。
为什么先学变量
在动手写任何功能之前,你得先知道”数据怎么存”。后面的运算符、条件判断、循环、函数,全都是在操作变量里的值。可以说,变量是 JavaScript 这座大楼的地基。地基没打牢,上面盖什么都晃。
这一篇我们会讲清四件事:怎么声明变量(let/const/var 的区别)、JS 里能装哪些类型的数据、怎么查看一个值的类型、以及新手最容易栽进去的”类型自动转换”大坑。
声明变量的三种方式
JS 里有三种声明关键字,现代写法主要用前两个,第三个是历史遗留。我们先看代码:
let age = 18; // 可变
const name = '小明'; // 常量,不能再改
var old = '老写法'; // 历史遗留,尽量别用
let:可以重新赋值的变量
let 声明一个可以重新赋值的变量。适合那些”值会变”的场景,比如游戏分数、计数器、用户实时输入。
let score = 60;
console.log(score); // 60
score = 95; // ✅ let 可以改
console.log(score); // 95
注意第 4 行只写 score = 95,不要重复写 let。let 只在”第一次声明”时用一次,之后改值直接写变量名。重复声明 let score = 100 会报错。
const:声明后不可改的常量
const 声明一个常量,赋值后不能再改。能用 const 就尽量用 const,它让代码更可预测——别人(和你三周后的自己)不会意外改掉它,调试时少很多”谁把值改了”的悬案。
const pi = 3.14;
console.log(pi); // 3.14
// pi = 3.15; // ❌ 报错:Assignment to constant variable
不过有个容易误解的点:const 锁的是”盒子不能换”,不是”盒子里的内容不能动”。如果盒子里放的是对象或数组,对象内部的属性、数组里的元素还是能改的:
const user = { name: '小明' };
user.name = '小红'; // ✅ 可以,改的是对象内部属性
console.log(user); // { name: '小红' }
// user = { name: '小刚' }; // ❌ 不行,不能把整个盒子换成另一个对象
var:了解即可,别再用
var 是 ES5 时代的老写法,有两个毛病:一是它没有”块级作用域”(后面讲作用域会细说),容易在循环里出 bug;二是它存在”变量提升”,声明会偷偷跑到作用域顶部,让代码行为难以预测。新项目基本淘汰,看到老代码认识就行,自己写一律用 let/const。
经验法则
默认写
const,只有当这个值确实需要被重新赋值时,才改成let。这能逼着你提前想清楚:这个值到底变不变?
JS 里的数据类型
JS 是”弱类型”语言——你不用提前声明变量装什么类型,赋什么就是什么,甚至同一个变量还能中途换成别的类型(虽然不推荐这么干)。数据类型分两大类:
原始类型(Primitive,直接存值)
这些类型”小而简单”,变量里直接存的就是值本身:
string字符串:'你好'、"hello",表示一段文字。number数字:42、3.14,JS 不区分整数和小数,统一都是number。boolean布尔:true/false,表示”真/假""开/关”,是条件判断的核心。null空值:主动表示”这里有意放了个空”。undefined未定义:变量声明了但还没赋值时的默认状态。symbol/bigint:较进阶,先知道存在即可,日常少见。
引用类型(Reference,存的是地址)
object对象:包括普通对象{}、数组[]、函数等。它存的是”这块数据在内存里的地址”,变量里放的是地址牌,不是数据本身。
看代码直观感受一下:
const s = '文字'; // string
const n = 100; // number
const b = true; // boolean
const empty = null; // null
let notSet; // undefined(没赋值,自动是 undefined)
const obj = { a: 1 }; // object
原始类型和引用类型的区别(重要)
这个区别新手很容易懵,我们用生活比喻讲清楚。原始类型像”名片”——你把名片给别人,对方拿到的是复印件,他涂改自己的复印件,不影响你手里那张。引用类型像”家门钥匙”——你把钥匙配了一把给别人,两人开的是同一扇门,他在屋里挪了沙发,你进去看到的就是被动过的样子。
// 原始类型:各自独立
let a = 5;
let c = a; // c 拿到 a 的"复印件"
c = 10;
console.log(a); // 5,a 没变
// 引用类型:共享同一块数据
const arr1 = [1, 2, 3];
const arr2 = arr1; // arr2 拿到的是同一把"钥匙"
arr2.push(4);
console.log(arr1); // [1, 2, 3, 4],arr1 也跟着变了!
理解这点,能帮你避开”我明明改的是 b,怎么 a 也变了”的诡异 bug。
typeof:查看一个值是什么类型
不确定某个值是什么类型时,用 typeof 问它。它返回一个小字符串告诉你类型:
typeof 'hi' // "string"
typeof 42 // "number"
typeof true // "boolean"
typeof {} // "object"
typeof [] // "object" ← 数组也是 object,记住
typeof undefined // "undefined"
typeof null // "object" ← 历史 bug,记住就行
typeof function(){} // "function"
最后两行是 JS 著名的”坑”:typeof null 竟然返回 "object",typeof 数组也返回 "object"。前者是语言早期的设计失误,改不掉了,记住即可;后者说明光靠 typeof 分不清”普通对象”和”数组”,要区分数组得用 Array.isArray(x)。
最容易踩的坑:类型自动转换
JS 在某些情况下会”自作主张”把类型转来转去,常常让人困惑。这就是所谓的”弱类型”带来的副作用:
'5' + 1 // "51" 字符串拼接,数字被转成字符串
'5' - 1 // 4 减法没有拼接语义,字符串被转成数字
'5' * 2 // 10 乘法也一样,字符串被转成数字
1 == '1' // true == 会先转换类型再比较
1 === '1' // false === 严格比较,类型不同直接 false
看第一行:'5' 是字符串,1 是数字,加号遇到字符串就变成”拼接”,于是 1 被变成 '1',拼成 "51"。再看第二行:减号没有”拼接”这回事,JS 就把 '5' 转成数字 5 再减,得到 4。同样是 '5' 配一个数字,加和减结果天差地别,这就是坑。
这就是为什么前面强调永远用 === 而不是 ==。== 会帮你偷偷转换类型再比较(1 == '1' 竟然是 true),结果常常不符合直觉;=== 不帮你转换,类型不同直接 false,比较结果更可预测,能避开一大类隐蔽 bug。
实战中正确的做法:先显式把类型转对,再比较:
const input = '18'; // 比如从输入框拿到的,默认是字符串
if (input === 18) {
console.log('不会进这里,因为 "18" 不等于 18');
}
if (Number(input) === 18) {
console.log('先把字符串转成数字再比,才进这里');
}
常用的显式转换函数:Number('18') 转数字、String(18) 转字符串、Boolean(0) 转布尔。别依赖 JS 自动帮你转,主动转最安全。
变量命名的讲究
顺带一提,变量名不是随便起的。几条规矩:
- 只能用字母、数字、下划线
_、美元符$,且不能以数字开头。 - 区分大小写:
age和Age是两个不同的变量。 - 不能用
let、const、if这类”关键字”当名字。 - 推荐”见名知意”:
userName比a好,cartCount比n好。多个单词用驼峰式(myScore),首字母小写。
这一篇你该记住的
- 变量像”贴标签的盒子”,用来存和取数据;程序能”记住”东西全靠它。
- 用
let存会变的值,用const存不变的值,别用var。const锁的是盒子不能换,盒子里对象/数组的内容还能改。 - 数据类型分原始类型(string/number/boolean/null/undefined…)和引用类型(object);引用类型多人共享同一份数据。
typeof看类型,但typeof null是"object"、typeof数组也是"object"这两个老坑要记得。- 比较一律用
===,别用会偷偷转类型的==;需要时先用Number()等显式转换再比。
下一篇我们讲运算符与表达式——加减乘除、> < 比较、还有 && || 这些逻辑运算,它们是把数据”算”出结果的工具,有了变量存值,下一步自然就是”算”起来。