这一章讲的是:怎么让程序「做判断、做选择、重复干活」。代码里的英文单词不用会读,把它们当固定写法记住就行,每个符号我都会用中文讲清意思。
| === | 严格相等:值和类型都要一样,才算相等 |
| !== | 不等于:只要不一样就是 true(真) |
| > < | 大于、小于 |
| >= <= | 大于或等于、小于或等于 |
比较的结果只有两种:true(真,成立)或 false(假,不成立)。
== 比较时会偷偷把两边的类型转成一样再比,比如带引号的文字 "1" 和数字 1,用 == 会判成相等。很多莫名其妙的 bug 就是它惹的祸,是出了名的坑。下面「动手试」里你会亲眼看到。// 端口是不是 443(严格相等) port === 443 // 端口是不是「不是 443」 port !== 443 // 数量是不是大于 10 count > 10 // 数量是不是大于或等于 10 count >= 10
| && | 「与」:两边都为真,结果才为真 |
| || | 「或」:只要有一边为真,结果就为真 |
| ! | 「非」:取反,真变假、假变真 |
// 登录了「并且」是会员,才为真 isLogin && isVip // 登录了「或者」是会员,有一个就为真 isLogin || isVip // 「没有」登录 !isLogin
还有一个小聪明叫短路:用 && 时,如果前面已经是假,整个结果注定是假,后面就直接不看了。用 || 时前面是真,后面也不看了。程序靠这个省力气,后面写判断时经常用到。
程序里经常遇到「空」:null 和 undefined 都表示「没有值」。处理不好,程序就会报错罢工。这两个符号就是专门防这个的:
const name = input ?? "默认"; // input 是 null 或 undefined 时 // 才用 "默认",有值就用它自己的值 const host = node?.server?.host; // 一层一层往里读 // 中间任何一层是空的,整体就是 undefined // 不会报错
要读好几层深的数据(比如订阅配置)时,?. 是必备的:少了它,中间缺一层,程序直接报错崩掉;有了它,最多拿到一个 undefined,还能继续往下走。
| + - * / | 加、减、乘、除,和数学里一样 |
| % | 取余:只要除完剩下的那个数 |
| ** | 乘方:一个数乘自己好几次 |
// 10 除以 3 余 1,结果是 1 10 % 3 // 2 的 3 次方(2×2×2),结果是 8 2 ** 3
if 是「如果……就……,否则如果……,否则……」,适合多种情况挨个判断:
if (port === 443) {
console.log("是标准端口");
} else if (port > 1000) {
console.log("高位端口");
} else {
console.log("其他");
}
从上往下挨个试:哪个条件先成立,就执行哪一段,后面的不再看;全都不成立,就走最后的 else。
如果只是简单的二选一,用三元更短,一行写完:
const label = tls ? "加密" : "明文"; // tls 是真,就取 "加密" // tls 是假,就取 "明文"
写法一:for,按下标一个一个取。i 从 0 开始数,每轮加 1,到 list.length(数组长度)为止。
for (let i = 0; i < list.length; i++) {
console.log(list[i]);
}
写法二:for...of,直接遍历每个元素。不用管下标,最省心,遍历数组时最常用这种:
for (const item of list) {
console.log(item);
}
写法三:forEach,自带下标。既要元素、又想要它是第几个时用它:
list.forEach((item, i) => {
console.log(i, item);
});
// i 是下标(从 0 开始)
// item 是元素本身
写法四:while,条件成立就一直转。不知道要转多少圈、只知道「什么时候停」时用它,注意别忘了让条件有机会变假,不然会死循环:
while (count > 0) {
count--;
// 每轮减 1,减到 0 就停
}
下面的代码可以直接改,点「运行」就能在页面里真的跑一遍,看结果对不对。改错了也不怕,出错会告诉你错在哪一类。
同样是比较「文字 1」和「数字 1」,看两个结果为什么不一样。
一个给默认值,一个读空对象也不报错。
先用三元做个二选一,再用 for...of 把节点地区一个个打印出来。
5 道选择题,点一下选项就知道对错,错了会告诉你错在哪。
已答对 0 / 5443 是加密网页(https)的标准端口。Worker 里判断请求该往哪条路走、检查节点配置对不对,第一步往往就是拿端口和 443 严格比较——用 === 而不是 ==,就是怕类型被偷偷转了之后误判。
if (port === 443) {
console.log("是标准端口");
}
订阅配置是一层套一层的数据:节点下面有 server,server 下面才有 host。有的节点写法不全,中间可能缺一层。用 ?. 读,缺了就拿到 undefined,后面再给个默认值,程序不会当场报错停摆。
const host = node?.server?.host ?? "未知"; // 中间缺任何一层都不报错 // 最后兜底给 "未知"
tg-bot 的订阅到期提醒就是这个套路:把所有订阅拿出来,用 for...of 一个一个过,发现哪个快到期了就发提醒。列表里有 5 个就查 5 遍,有 100 个就查 100 遍,代码一行都不用多写。
for (const sub of subs) {
if (sub.daysLeft <= 3) {
console.log(sub.name + " 快到期了");
}
}
一句话记住这一章:比较永远用 ===,空值用 ?? 和 ?. 兜底,判断用 if 和三元,重复的事交给 for...of。