You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
199 lines
12 KiB
199 lines
12 KiB
// 03 · 运算符
|
|
// 学练复习一体:概念总结 → 示范 → 轮到你
|
|
// 跑法:Quokka / 右上角 ▷ / node 本文件
|
|
// 示范区每行后注释是【预期输出】,跑完自己对答案
|
|
|
|
// ═════ 概念总结 ═════
|
|
//
|
|
// 1. 算术运算符
|
|
// ┌──────┬────────────┬──────────┬──────────────────────────┐
|
|
// │ 符号 │ 含义 │ 例子 │ 结果 │
|
|
// ├──────┼────────────┼──────────┼──────────────────────────┤
|
|
// │ + │ 加 │ 2 + 3 │ 5 │
|
|
// │ - │ 减 │ 5 - 2 │ 3 │
|
|
// │ * │ 乘 │ 4 * 3 │ 12 │
|
|
// │ / │ 除 │ 10 / 4 │ 2.5(JS 除法不取整!) │
|
|
// │ % │ 取余(模) │ 10 % 3 │ 1 │
|
|
// │ ** │ 幂(次方) │ 2 ** 3 │ 8 │
|
|
// └──────┴────────────┴──────────┴──────────────────────────┘
|
|
// 两个初学重点:
|
|
// - JS 里 10 / 4 = 2.5,不像有些语言整数相除会取整。
|
|
// - % 取余超常用:判断奇偶(n % 2 === 0 就是偶数)、循环里做周期。
|
|
//
|
|
// ⚠️ 负数取余的坑:判奇偶要用 === 0 不要用 === 1
|
|
// JS 里取余结果的符号跟着"被除数"走,负数取余是负的:
|
|
// 7 % 2 // 1 -7 % 2 // -1 ← 不是 1!符号跟着 -7
|
|
// 所以判奇偶:
|
|
// n % 2 === 0 // ✅ 判偶数,对正负数都成立
|
|
// n % 2 === 1 // ❌ 判奇数,遇负数会漏:-7%2 是 -1,=== 1 得 false → 误判成偶数
|
|
// 结论:判奇偶一律用 n % 2 === 0(判偶),再用 else 处理奇数。别用 === 1。
|
|
//
|
|
// 2. 赋值运算符
|
|
// = 是"赋值"(把右边存进左边),下面是简写:
|
|
// ┌────────┬──────────────┬────────┐
|
|
// │ 写法 │ 等价于 │ 说明 │
|
|
// ├────────┼──────────────┼────────┤
|
|
// │ x += 5 │ x = x + 5 │ 加等于 │
|
|
// │ x -= 5 │ x = x - 5 │ 减等于 │
|
|
// │ x *= 2 │ x = x * 2 │ 乘等于 │
|
|
// │ x /= 2 │ x = x / 2 │ 除等于 │
|
|
// └────────┴──────────────┴────────┘
|
|
//
|
|
// 3. 比较运算符 → 结果是布尔值 ⭐
|
|
// ┌───────────────┬──────────────────────────────┬──────────┬──────────┐
|
|
// │ 符号 │ 含义 │ 例子 │ 结果 │
|
|
// ├───────────────┼──────────────────────────────┼──────────┼──────────┤
|
|
// │ > < >= <= │ 大小比较 │ 5 > 3 │ true │
|
|
// │ === │ 严格等于(值和类型都要相等) │ 1 === 1 │ true │
|
|
// │ !== │ 严格不等 │ 1 !== 2 │ true │
|
|
// │ == │ 松散等于(会偷偷转类型) │ 1 == '1' │ true ⚠️ │
|
|
// └───────────────┴──────────────────────────────┴──────────┴──────────┘
|
|
// ⭐⭐ 最重要的一条规则:永远用 ===,别用 ==
|
|
// == 会做"隐式类型转换",制造诡异结果:
|
|
// 1 == '1' // true ← 数字 1 和字符串 '1' 被判相等?!
|
|
// 1 === '1' // false ← === 看类型,数字 ≠ 字符串,正确
|
|
// 0 == '' // true ← 更离谱
|
|
// 记死这条:比较一律用 === 和 !==。这是 JS 最著名的坑之一。
|
|
//
|
|
// 4. 逻辑运算符
|
|
// ┌──────┬───────────┬──────────────────┐
|
|
// │ 符号 │ 含义 │ 口诀 │
|
|
// ├──────┼───────────┼──────────────────┤
|
|
// │ && │ 与(AND) │ 都为真才真 │
|
|
// │ || │ 或(OR) │ 有一个真就真 │
|
|
// │ ! │ 非(NOT) │ 真假反转 │
|
|
// └──────┴───────────┴──────────────────┘
|
|
// true && false // false true || false // true !true // false
|
|
// 常用于条件判断:age >= 18 && hasTicket(成年且有票)。
|
|
//
|
|
// 5. 一个坑:+ 对字符串是"拼接" ⭐
|
|
// 1 + 2 // 3 ← 数字相加
|
|
// '1' + '2' // '12' ← 字符串拼接
|
|
// '1' + 2 // '12' ← 只要有一个是字符串,就拼接!
|
|
// 1 + '2' + 3 // '123' ← 从左到右,一旦变字符串后面全拼
|
|
// 其他运算符(- * /)不会拼接,反而会把字符串转成数字再算:
|
|
// '6' - 2 === 4、'6' * 2 === 12。只有 + 特殊。
|
|
//
|
|
// 6. 类型转换:显式 vs 隐式 ⭐⭐
|
|
// 上面这些坑的根源,都是 JS 在偷偷"转类型"。
|
|
// 隐式转换(JS 自作主张,坑的来源)—— 你没让它转,它自己转了:
|
|
// '5' + 3 // '53' ← 偷偷把 3 转成字符串,拼接
|
|
// '5' - 3 // 2 ← 偷偷把 '5' 转成数字
|
|
// 0 == '' // true ← 偷偷都转成数字比较
|
|
// 'abc' - 1 // NaN ← 转不成数字 → NaN(会像病毒一样传染后续计算)
|
|
// 显式转换(你主动写,推荐 ✅)—— 意图清楚、无意外:
|
|
// Number('42') // 42 Number('abc') // NaN ← 转不了就是 NaN
|
|
// parseInt('42px')// 42 parseFloat('3.14') // 3.14
|
|
// String(42) // '42'
|
|
// Boolean('') // false Boolean('hi') // true Boolean(0) // false
|
|
// 方向性差异(记住):
|
|
// - 数字 → 字符串:几乎总能成功
|
|
// - 字符串 → 数字:可能失败,失败得 NaN(处理用户输入时要留心)
|
|
// 原则:能用显式(Number()/String())就别靠隐式。
|
|
//
|
|
// 7. TypeScript 能克服这些坑吗?—— 部分能 ⭐
|
|
// TS 在写代码时(编译期)检查类型,能挡一大类,但不是全部:
|
|
// ┌──────────────────────────────────────────────┬───────────────┐
|
|
// │ 坑 │ TS 能挡吗 │
|
|
// ├──────────────────────────────────────────────┼───────────────┤
|
|
// │ '5' - 3(类型不匹配的运算) │ ✅ 编译期报错 │
|
|
// │ 0 == ''(乱比较) │ ✅ 报错 │
|
|
// │ '5' + 3(拼接,语法合法) │ ❌ 不管 │
|
|
// │ 外部数据(输入/请求/JSON.parse)类型错 │ ❌ 只信标注 │
|
|
// │ 运行时才暴露的问题 │ ❌ 类型已消失 │
|
|
// └──────────────────────────────────────────────┴───────────────┘
|
|
// 心智模型:TS 是"写代码时的第一道墙",挡掉大部分手滑;但 + 拼接、外部数据
|
|
// 这些盲区,仍要靠显式转换 + 校验输入兜底。理解 JS 转换原理,是用好 TS 的前提。
|
|
//
|
|
// ✅ 本主题要点回顾
|
|
// 1. 算术:/ 不取整、% 取余判奇偶、** 次方
|
|
// 2. 赋值简写:+= -= *= /=
|
|
// 3. 比较永远用 === / !==,别用 == ⭐⭐
|
|
// 4. 逻辑:&&(都真)、||(有一真)、!(反转)
|
|
// 5. + 遇字符串会拼接,其他运算符会转数字 ⭐
|
|
// 6. 能用显式转换(Number()/String())就别靠隐式 ⭐
|
|
// 7. TS 能挡"类型不匹配"的坑,但挡不住 + 拼接和外部数据 —— 显式转换的习惯不能丢
|
|
|
|
// ═════ 示范 ═════
|
|
|
|
// ── 1. 算术运算符 ─────────────────────────────────
|
|
console.log(2 + 3) // 5
|
|
console.log(5 - 2) // 3
|
|
console.log(4 * 3) // 12
|
|
console.log(10 / 4) // 2.5 ← JS 除法不取整!
|
|
console.log(10 % 3) // 1 ← 取余
|
|
console.log(2 ** 3) // 8 ← 2 的 3 次方
|
|
|
|
// ── 2. % 取余判断奇偶 ⭐ ──────────────────────────
|
|
console.log(10 % 2) // 0 ← 余 0 → 偶数
|
|
console.log(7 % 2) // 1 ← 余 1 → 奇数
|
|
console.log(10 % 2 === 0) // true ← 判断偶数的标准写法
|
|
|
|
// ── 3. 赋值简写 ───────────────────────────────────
|
|
let x = 10
|
|
x += 5 // 等价 x = x + 5
|
|
console.log(x) // 15
|
|
x *= 2 // 等价 x = x * 2
|
|
console.log(x) // 30
|
|
|
|
// ── 4. 比较运算符 → 布尔值 ────────────────────────
|
|
console.log(5 > 3) // true
|
|
console.log(5 <= 4) // false
|
|
console.log(1 === 1) // true
|
|
console.log(1 !== 2) // true
|
|
|
|
// ── 5. === vs == 的坑 ⭐⭐(最重要)────────────────
|
|
console.log(1 === '1') // false ← 严格:类型不同 → 不等(正确做法)
|
|
console.log(1 == '1') // true ← 松散:偷偷转类型 → 相等(危险!)
|
|
console.log(0 == '') // true ← == 的离谱行为
|
|
// 结论:永远用 ===,别用 ==
|
|
|
|
// ── 6. 逻辑运算符 ─────────────────────────────────
|
|
console.log(true && false) // false ← 都真才真
|
|
console.log(true || false) // true ← 有一真就真
|
|
console.log(!true) // false ← 反转
|
|
|
|
const age = 20
|
|
const hasTicket = true
|
|
console.log(age >= 18 && hasTicket) // true ← 成年且有票
|
|
|
|
// ── 7. + 遇字符串会拼接 ⭐ ────────────────────────
|
|
console.log(1 + 2) // 3 ← 数字相加
|
|
console.log('1' + '2') // '12' ← 字符串拼接
|
|
console.log('1' + 2) // '12' ← 有一个字符串就拼接
|
|
console.log(1 + '2' + 3) // '123' ← 从左到右,变字符串后全拼
|
|
|
|
// 其他运算符反而会把字符串转成数字:
|
|
console.log('6' - 2) // 4 ← - 让 '6' 变数字 6
|
|
console.log('6' * 2) // 12 ← * 同理
|
|
|
|
// ═════ 轮到你 ═════
|
|
|
|
// 👇 轮到你(把 ??? 换掉,取消注释,跑一下对答案)
|
|
|
|
// 练习 A:判断 15 是不是偶数(用 % 和 ===),应打印 false
|
|
// console.log(15 % 2 === 0)
|
|
|
|
// 练习 B:一个人 age = 16,判断"成年 且 有票",应打印 false
|
|
// const myAge = ???
|
|
// const ticket = true
|
|
// console.log(??? >= 18 && ticket)
|
|
|
|
// 练习 C:猜一下 '5' + 3 和 '5' - 3 分别是什么?先猜再取消注释验证
|
|
// console.log('5' + 3) // 你猜:___
|
|
// console.log('5' - 3) // 你猜:___
|
|
|
|
// 练习 A:判断 15 是不是偶数 → 要用 === 才是"判断"
|
|
console.log(15 % 2 === 0) // false ← 15%2 是 1,1===0 为 false
|
|
console.log(15 % 2) // 1 ← 对比:这只是算余数,不是判断
|
|
|
|
// 练习 B:age=16,判断"成年(>=18)且有票"
|
|
const myAge = 16
|
|
const ticket = true
|
|
console.log(myAge >= 18 && ticket) // false ← 16 不够 18,&& 整体为 false
|
|
|
|
// 练习 C:先猜后验(你猜的 '53' 和 2 都对!)
|
|
console.log('5' + 3) // '53' ← + 遇字符串 → 拼接
|
|
console.log('5' - 3) // 2 ← - 把 '5' 转成数字 → 5-3
|
|
|