JavaScript 零基础教程 · 第二章

变量与数据类型

代码里的英文单词不用怕,把它们当固定写法记下来就行,每个词的意思都会用中文讲清楚。这一章最重要的是分清一件事:带引号的是文字,不带引号的才是数字,它俩混在一起算,是新手最常踩的坑。

1这一章学什么

学完这一章,你要会四件事:分清 let 和 const(谁能改、谁不能改)、认识七种数据类型、会用 typeof 查一个东西是什么类型,会用 Number / String / Boolean 做类型转换,并且避开 "1" + 2 这个坑——文字加数字,得到的不是算数结果。

2概念

一共六个知识点,看不懂的地方先跳过,做完后面的「动手试」再回来看就通了。

① 变量:给数据起个名字

变量就像一个贴了标签的盒子:把数据放进去,起个名字,以后喊名字就是用里面的数据。声明(创建)变量有三种写法:

const pi = 3.14      // const:常量,赋值后不能改
let count = 5        // let:变量,之后可以改
count = 6            // 改成 6,没问题
var old = 1          // var:老写法,新代码不用它
规矩只有一条:默认用 const,需要改值时才用 let。

变量名要用英文,写法叫「小驼峰」:第一个单词全小写,后面的单词首字母大写,比如 myCount、userName。名字要见名知意——看到 myCount 就知道里面装的是「我的计数」,不要起 a、x1 这种看不懂的名字。

② 七种基本数据类型

JavaScript 里的数据分七种基本类型。先混个脸熟,object 和 array 是第四章的主角,这一章认识一下就行。

类型是什么
string字符串 用引号包起来的文字,如 "你好"、"123"。记住:"123" 是文字,不是数字!
number数字 数字,如 42、3.14。整数和小数不分家,都是 number。还有个特殊值 NaN,意思是「不是数字」(比如文字硬转数字失败时就会得到它)。
boolean布尔 只有两个值:true(真)和 false(假),专门用来做条件判断。
undefined未定义 声明了变量但没给它赋值,就是这个值。意思是「还没给」。
null空 明确表示「空」,是程序员手动写上去的空。和 undefined 的区别:undefined 是还没给,null 是故意给个空。
object对象 把一堆带名字的数据装在一起,如 { name: "a" }。(第四章主角)
array数组 一个有序的列表,如 [1, 2, 3],按顺序排队装数据。(第四章主角)

③ typeof:查一个东西是什么类型

拿不准手里的数据是哪种类型,就用 typeof 问一下,它会用文字回答你:

typeof 42       // 得到 "number",是数字
typeof "abc"    // 得到 "string",是文字
typeof true     // 得到 "boolean",是布尔

下面的「动手试」第 3 段就能亲手跑一遍这三行。

④ 类型转换三件套

类型不对时,可以用三个工具互相转换,名字记牢:Number() 转数字、String() 转文字、Boolean() 转布尔。

Number("123")    // 得到 123,文字变数字
String(123)      // 得到 "123",数字变文字
Boolean(0)       // 得到 false,0 是「假」

⑤ 真值与假值:什么被当作「假」

做条件判断时,不光 boolean 能用,任何值都会被当成「真」或「假」。被当作假的只有六个,背下来:

false0""nullundefinedNaN

其中 "" 是空字符串(引号里什么都没有的文字)。除了这六个,其余全是真——特别注意:空数组 [] 和空对象 {} 也是真,别看它空,它不算假。还有文字 "0" 也是真,因为它是非空的文字。

⑥ 新手第一坑:「文字 + 数字」不是算数

重点,这个坑人人都会踩一次

"1" + 2 得到的是文字 "12",不是 3。因为在 JavaScript 里,加号 + 有两个工作:两边都是数字时做加法;只要碰上一边是文字,它就改行做「拼接」——把另一边也当文字,前后接起来。所以 "1" + 2 是把 "1" 和 "2" 接成 "12"。

破解办法:算数之前先用 Number() 把文字转成数字。Number("1") + 2 就是正经算数,得到 3。

console.log("1" + 2)           // "12",拼接,坑!
console.log(Number("1") + 2)   // 3,先转再算,对了

补一句:减号 - 没有这个毛病,它只做算数,会先偷偷把文字转成数字。所以 "10" - 5 得到 5。只有加号会变拼接。

3动手试

点「运行」,代码会真的在这一页里跑一遍,结果显示在下面。输出里带引号的是文字,不带引号的是数字,看输出时先看引号。

试一:文字加数字,会发生什么

console.log("1" + 2)           // 第一行:文字 + 数字
console.log(Number("1") + 2)   // 第二行:先转成数字再加
先猜一下两行分别输出什么,再点运行对答案。

看结果:第一行输出 "12",带引号,是文字——加号把 2 拼上去了。第二行输出 3,不带引号,是数字——先用 Number() 转好,就是正经加法。这就是本章第一坑的现场,记住:算数前先转数字。

试二:版本号为什么不能当文字比

console.log("2.04.10" > "2.04.9")   // 当文字比,结果是?

// 修法:按点拆开,每段转成数字再比
const a = "2.04.10".split(".").map(Number)   // 得到 [2, 4, 10]
const b = "2.04.9".split(".").map(Number)    // 得到 [2, 4, 9]
console.log(a[2] > b[2])   // 第三段 10 > 9,结果是?
第一行问的是:2.04.10 比 2.04.9 大吗?

看结果:第一行输出 false——明明 10 比 9 大,却说不大!因为文字比大小是一个字一个字从左往右比的:前面的 2.04. 都一样,比到 "1" 对 "9",1 比 9 小,当场就判输了,压根没机会看到 10 是一个整体。

第二段先用 split(".") 按点拆开,再用 map(Number) 把每段转成数字,第三段就是数字 10 对数字 9,输出 true,这才比对了。这正是你自己的 SurgeModuleTools 踩过、又在 2.04.2 修好的那个坑,案例区还会细讲。

试三:用 typeof 查类型

console.log(typeof 42)      // 数字查出来是什么?
console.log(typeof "abc")   // 文字查出来是什么?
console.log(typeof true)    // true 查出来是什么?
typeof 的回答本身是文字,所以输出会带引号。

看结果:三行依次是 "number"、"string"、"boolean"。以后拿到一个数据拿不准类型,先 typeof 问一下再动手,能少踩很多坑。

4练一练

五道选择题,点一个选项马上判对错。选错了会告诉你错在哪,再换一个试试;选对了会告诉你为什么对。

答对进度0 / 5

5适用案例

这一章的东西不是课本练习,你自己的三个项目里全在用。

案例一

tg-bot 的 KV 计数坑

你的 tg-bot 把数据存在 Cloudflare 的 KV 里。要记住:从 KV 里取出来的东西,永远是文字,哪怕你存进去的时候是数字。

let n = await KV.get("count")   // 取出来的是文字 "5",不是数字 5
n + 1          // 得到 "51"!拼接的坑
Number(n) + 1  // 得到 6,先转再加才对

计数器、次数统计这类功能,只要数据经过 KV,就必须在算数前套一层 Number()。不套,计数就会从 5 变成 "51"、再变成 "511",越加越离谱,还不报错,很难查。

案例二

SurgeModuleTools 的版本号比较

模块要判断「线上有没有新版本」,就得比版本号大小。旧版的做法是直接把两个版本号当文字比:

"2.04.10" > "2.04.9"   // 结果是 false,比错了

文字是逐字比的:比到 "1" 对 "9" 就停了,所以 2.04.10 反而被判成比 2.04.9 小,新版本在眼前也提示不出来。2.04.2 的修法就是上面「动手试」试二那套:按点拆开、逐段 Number() 转成数字再比,10 才能赢 9。凡是「长得像数字的文字」,比大小之前都要先想一想这一条。

案例三

Surge 脚本里 body 的文字 ⇄ 对象转换

Surge 脚本处理响应时,$response.body 拿到的是一整段文字,直接取里面的字段是取不到的,要先转成对象:

const obj = JSON.parse($response.body)   // 文字 → 对象
console.log(obj.name)                    // 转成对象后,才能这样取字段
const body = JSON.stringify(obj)         // 对象 → 文字,发出去之前转回去

记住这一对:JSON.parse() 把文字变对象,JSON.stringify() 把对象变文字。网络上传来传去的都是文字,程序内部干活要用对象,进门 parse、出门 stringify,是以后写脚本最常用的动作之一。

✓小结与小作业

一句话小结:默认用 const、要改才用 let;带引号的是文字、不带的是数字;加号碰上文字就变拼接,算数之前先用 Number() 转好——这一章抓住这三句,就够用了。

小作业

打开 Scriptable,把本章「动手试」的三段代码各跑一遍(代码块右上角可以复制),看看在 Scriptable 里输出是不是和这一页一样。

跑完之后,用你自己的话写一句总结:这一章你觉得最容易踩的坑是什么。可以直接写在这一课的 Notion 页面下面。