变量与数据类型
代码里的英文单词不用怕,把它们当固定写法记下来就行,每个词的意思都会用中文讲清楚。这一章最重要的是分清一件事:带引号的是文字,不带引号的才是数字,它俩混在一起算,是新手最常踩的坑。
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:老写法,新代码不用它
变量名要用英文,写法叫「小驼峰」:第一个单词全小写,后面的单词首字母大写,比如 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 能用,任何值都会被当成「真」或「假」。被当作假的只有六个,背下来:
其中 "" 是空字符串(引号里什么都没有的文字)。除了这六个,其余全是真——特别注意:空数组 [] 和空对象 {} 也是真,别看它空,它不算假。还有文字 "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,结果是?
看结果:第一行输出 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 查出来是什么?
看结果:三行依次是 "number"、"string"、"boolean"。以后拿到一个数据拿不准类型,先 typeof 问一下再动手,能少踩很多坑。
4练一练
五道选择题,点一个选项马上判对错。选错了会告诉你错在哪,再换一个试试;选对了会告诉你为什么对。
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 页面下面。