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.
30-Days-Of-JavaScript/js_notes/00-concepts/my-mistakes.md

178 lines
7.4 KiB

# 🕳️ 我的踩坑记录
> 这里记录我**自己真实犯过**的错(不是泛泛知识点)。复习时先扫这里 —— 我最容易在这些地方翻车。
> 每条格式:**错法 → 现象 → 正解 → 教训**,并标注**📍来源**(点开可回到原题)。
---
## A. 方法忘加括号
📍来源:`../04-strings/practice.js` 练习 A(`../04-strings/notes.md` §1)
```js
city.toUpperCase // ❌ 打印出 [Function: toUpperCase],不是结果
city.toUpperCase() // ✅ 加 () 才执行
```
- **现象**:打印出一堆 `[Function: xxx]` 而不是想要的值
- **教训**:**方法是"动作",必须加 `()`**;`.length` 是属性不加括号。分不清就问:这是"数据"还是"动作"?
## B. 模板字符串用错符号
📍来源:`../02-variables/practice.js` 第 6 组(`../01-basics/notes.md` §4)
```js
`我叫 &{myName}` // ❌ 用了 &,原样打印 "我叫 &{myName}"
`我叫 ${myName}` // ✅ 是 $ 不是 &
```
- **教训**:模板插值是 **`$` + `{}`**,不是 `&`。且只在反引号 `` ` `` 里生效。
## C. 方法名拼写错
📍来源:`../04-strings/practice.js` 练习 B
```js
email.spilt('@') // ❌ 报错:email.spilt is not a function
email.split('@') // ✅
```
- **现象**:`X is not a function`
- **教训**:看到 `is not a function`,先检查**拼写**。
## D. "能算 ≠ 能看见"(反复犯)
📍来源:`../04-strings/practice.js` 练习 E、`../06-arrays/practice.js` 练习 E(`../01-basics/notes.md` §5)
```js
array.join('-') // ❌ 算出来了但没打印,屏幕啥都没有
console.log(array.join('-')) // ✅
```
- **教训**:文件里**必须 `console.log`** 才看得到结果。裸表达式会算但不显示。
## E. 方法返回值没接住(反复犯)⭐
📍来源:`../04-strings/practice.js` 练习 D/E、`../06-arrays/practice.js` 练习 E
```js
sentence.split(' ') // ❌ 拆了但没接住,等于白拆
const words = sentence.split(' ') // ✅ 用变量接住
```
- **教训**:`slice / split / join / map / toUpperCase...` 都**返回新值、不改原**,必须用变量接住或直接打印。
## F. 改原 vs 返回新,分不清 ⭐⭐
📍来源:`../06-arrays/practice.js` 练习 D/E(`../06-arrays/notes.md` §4-5)
- **改原数组**:`push / pop / shift / unshift / splice`
- **返回新值(不改原)**:`slice / split / join / map / filter`
- `splice` 尤其坑:**返回的是"被删元素",不是修改后的数组** → 插入后要打印**原数组**,别打印返回值
```js
q.splice(1, 0, 'x') // 改的是 q 本身
console.log(q) // ✅ 打印原数组
console.log(q.splice(...)) // ❌ 打印的是被删元素([])
```
## G. slice 用 length-1 丢了最后一个字符
📍来源:`../04-strings/practice.js` 练习 D(`../04-strings/notes.md` §4)
```js
name.slice(1, name.length - 1) // ❌ -1 少取一位
name.slice(1) // ✅ 省略 end 取到结尾
```
- **教训**:`slice` **不含 end**;要取到结尾直接省略第二个参数。
## H. 变量没声明就赋值
📍来源:`../06-arrays/practice.js` 练习 E(`../02-variables/notes.md` §2-3)
```js
array = sentence.split(' ') // ❌ 裸奔,泄漏成全局变量(严格模式报错)
const array = sentence.split(' ') // ✅ 必须 const/let 声明
```
- **教训**:变量**一定先声明**。
## I. 引号不配对
📍来源:`../07-objects/practice.js` 练习 A(`../01-basics/notes.md` §4)
```js
title: "JavaScript' // ❌ 双开单关,整个文件从这里崩
title: "JavaScript" // ✅ 开关同一种
```
- **现象**:从这行起后面全报错
- **教训**:引号**开和关必须同种**。
## J. 变量名定义和使用对不上
📍来源:`../07-objects/practice.js` 练习 C
```js
const cat = {...}
Object.values(car) // ❌ car is not defined(定义 cat 用 car)
```
- **现象**:`X is not defined`
- **教训**:看到 `is not defined`,检查**名字是否一致**(typo)。
## K. 下标从 0 开始,越界读 undefined ⭐
📍来源:`../07-objects/practice.js` 练习 E(`../06-arrays/notes.md` §1)
```js
// 3 个元素:people[0] people[1] people[2]
people[3].name // ❌ 越界:Cannot read properties of undefined
```
- **教训**:下标**从 0 开始**,"第 N 个" = `[N-1]`;最后一个 = `[length-1]`
## L. 对象方法用了箭头函数,this 失效 ⭐⭐
📍来源:`../07-objects/practice.js` 练习 D(`../07-objects/notes.md` §7)
```js
describe: () => this.name // ❌ 箭头函数没有自己的 this → undefined
describe: function () { return this.name } // ✅ 用 function
describe: function () => {...} // ❌ 语法错:function 和 => 不能同时写
```
- **教训**:**对象方法用 `function`,不用箭头 `=>`**(箭头没有自己的 this)。两种写法只能选一种。
## M. const 同名声明两次
📍来源:`../07-objects/practice.js` 练习 D;又见 `../10-functions.js` 练习 F
```js
const student = {...}
const student = {...} // ❌ Identifier 'student' has already been declared
```
- **教训**:同作用域 `const` 不能重名;想留"错误对照"就**注释掉**旧的,别当活代码。
- **重演情境(10章F)**:迭代改进时【新写了一版更好的 `const repeat`,却忘了删/注释掉旧版】
→ 两个活的 `const repeat` → 整个文件直接报错跑不了。
改进代码时:**旧版要么删,要么注释成 ❌ 对照,绝不能两个都当活代码**。
## N. 以为"代码块能算出值、会自动返回"⭐⭐(概念推错,非手滑)
📍来源:`../10-functions.js` 概念区第 2 节(箭头函数)
```js
const add = (a, b) => { a + b } // ❌ 以为块算出 a+b 就会返回 → 实际返回 undefined
const add = (a, b) => a + b // ✅ 无 {}:右边是表达式(值),自动返回
const add = (a, b) => { return a + b } // ✅ 有 {}:块里必须手写 return
```
- **现象**:函数默默返回 `undefined`,**不报错**(最难查)
- **根源**:核心一句 —— **`=>` 右边期望一个「表达式」(能算出值的东西)**。
- 表达式(`a+b`)=【有值】→ 直接返回;能赋值 `const x = a+b`
- 代码块(`{...}`)=【一堆动作,不产值】→ 不能赋值 `const x = {a+b}` ❌ 报错
- 所以 `{ a+b }` 里那个 `a+b` 被算出来**却被丢弃**,函数无 return → undefined
- **教训**:别把"代码块"当"能出值的表达式"。**块不产值**,所以进了 `{}` 就必须自己 `return`
## O. 箭头函数返回对象忘加括号 ⭐
📍来源:`../10-functions.js` 概念区第 2 节
```js
const make = (name) => { name: name } // ❌ { 被当代码块,返回 undefined(不报错!)
const make = (name) => ({ name: name }) // ✅ () 逼它当表达式 → 返回对象
```
- **现象**:想返回对象,却得到 `undefined`,且**不报错**
- **根源**:对象字面量和代码块都以 `{` 开头,`=> {` 会被优先当**代码块**;
里面的 `name:` 又被当成**标签语句**(JS 给循环起名字的老语法,`名字:`),于是静默返回 undefined
- **教训**:箭头函数**直接返回对象**,用 `()` 把对象裹起来,逼回"表达式"语境。
---
## 🔁 高频报错 → 秒查表
| 报错信息 | 最可能的原因 | 看哪条 |
|---|---|---|
| `X is not a function` | 方法名拼错 | C |
| `X is not defined` | 变量名 typo / 没声明 | H、J |
| `Cannot read properties of undefined` | 下标越界 / 键不存在 | K |
| `has already been declared` | const 重名 | M |
| 打印出 `[Function: xxx]` | 方法忘加 `()` | A |
| 屏幕啥都没有 | 忘了 console.log / 没接住返回值 | D、E |
| 从某行起全报错 | 引号没配对 | I |
| 函数返回 `undefined`(不报错) | `{}` 里忘 return / 箭头返回对象没加 `()` | N、O |