diff --git a/js_notes/02-variables.js b/js_notes/02-variables.js index 4cd079d..683c768 100644 --- a/js_notes/02-variables.js +++ b/js_notes/02-variables.js @@ -22,6 +22,9 @@ // const PI = 3.14 // 常量,不会变 // let count = 0 // 会变的用 let;count = count + 1 ✅ // // PI = 3.15 // ❌ 报错:const 不能重新赋值 +// ⚠️ var 为啥"有坑"?一个典型:变量声明前就用它,var 会【静默给 undefined】 +// 把 bug 藏起来;而 const/let 会【当场报错】(TDZ),让你一眼发现。 +// (详见 10-functions.js "提升 hoisting" 一节) // // 3. 变量命名规则 ⭐ // 必须遵守(否则报错): @@ -54,11 +57,37 @@ // typeof undefined // 'undefined' // 小坑:typeof null 会返回 'object',这是 JS 历史遗留 bug,记住即可。 // -// 6. undefined vs null -// - undefined:系统给的"还没值"。声明了没赋值就是它。 -// - null:你主动给的"这里是空的"。 +// ── 三个最爱混的值,typeof 都出人意料(速查)⭐⭐ ── +// ┌───────────┬──────────────┬────────────────────────────────────┐ +// │ 值 │ typeof 结果 │ 一句话 + 坑 │ +// ├───────────┼──────────────┼────────────────────────────────────┤ +// │ undefined │ 'undefined' │ 系统给的"还没值";自成一个类型 │ +// │ null │ 'object' ⚠️ │ 你给的"空";typeof 说它 object 是坑 │ +// │ NaN │ 'number' ⚠️ │ 无效数字,属 number;NaN!==NaN 是坑 │ +// └───────────┴──────────────┴────────────────────────────────────┘ +// 记:null 不是真 object(历史 bug);NaN 不是"不是数字",它就是 number。 +// 详见下方 §6(undefined vs null)、§7(NaN)。 +// +// 6. undefined vs null ⭐ +// 两个都表示"没有",区别在【谁放的、是不是有意】: +// - undefined:系统给的"还没值"(默认状态)。像杯子你还没倒过。 +// - null:你主动给的"这里【有意】空着"(刻意清空/占位)。像杯子你特意倒空并标记。 // let x; console.log(x) // undefined ← 没赋值,系统默认 // let y = null // null ← 你主动清空 +// null === undefined // false ← 概念不同:一个"未设置",一个"设为空" +// +// ── null 到底是什么?怎么理解 ⭐ ── +// null 是一个【独立的原始值】,自成一类,类里只有它一个成员;含义="有意的空"。 +// • typeof null // 'object' ← 这是 1995 年的历史 bug(底层用全 0 表示,被误判)。 +// 全世界老代码都依赖它了,改了会崩,只好将错就错。→ null 不是对象,是原始值! +// (呼应 00-concepts/value-vs-reference.md:null 明列在"原始值"栏) +// • 怎么判断是不是 null?直接用 === 就行,可靠(不像 NaN 连自己都不等): +// if (x === null) { ... } // ✅ null === null 成立 +// // ❌ 别用 typeof x === 'object' 判 null:{}、[] 也是 'object',会误伤 +// • 什么时候用:"这位置将来会有个对象,但现在还没有"→ 用 null 明确占位: +// let currentUser = null // 还没登录,主动标记"当前无用户" +// currentUser = { name: 'Tom' } // 登录后再填 +// 比放 undefined 更能表达"我【知道】这里暂时空,不是忘了"(agent 代码常见)。 // // 7. NaN / Infinity 都属于 number ⭐ // NaN(Not a Number)名字唬人,但它自己的类型偏偏是 number —— @@ -82,6 +111,7 @@ // 2. 优先 const,要改才用 let,别用 var ⭐ // 3. 命名:小驼峰、有意义、不能数字开头 // 4. 常用类型:number / string / boolean,外加 undefined / null +// (null 是"有意的空",独立原始值;判断用 === null,typeof null==='object' 是坑) // 5. typeof 查类型(注意 typeof null === 'object' 是坑) // 6. NaN / Infinity 都属于 number;NaN !== NaN,判断用 Number.isNaN() ⭐ diff --git a/js_notes/07-objects.js b/js_notes/07-objects.js index 96a5916..9630725 100644 --- a/js_notes/07-objects.js +++ b/js_notes/07-objects.js @@ -9,6 +9,23 @@ // 数组是"有序列表"(按下标),对象是"带标签的数据"(按名字)。 // 用来表示真实世界的东西:一个人、一辆车。 // +// 0. 对象到底是什么?——两层含义 ⭐⭐(总纲) +// 表面:对象 = 键值对(键: 值)的集合,用 {} 装(就是下面 §1 讲的)。 +// 本质:JS 的类型分【两大阵营】—— 原始值 vs 对象: +// • 原始值(7 个):number / string / boolean / undefined / null / bigint / symbol +// • 对象(就 1 个大类,却装下几乎其余一切):普通 {}、【数组】、【函数】、Date、正则…… +// 它们本质【都是对象】,只是"特殊的对象"。 +// 判据:能往它身上挂属性(键:值)的,就是对象 —— +// const arr = [1, 2]; arr.myTag = 'hi' // 数组能挂 → 数组是对象 +// const fn = () => {}; fn.count = 5 // 函数能挂 → 函数是对象 +// typeof [] // 'object' ← 数组是对象 +// typeof (()=>{}) // 'function' ← 函数特殊显示,但它也是对象 +// 这一条解释了你早前所有疑问:typeof [] 是 object、函数能当值传/能挂属性、 +// {} 叫"对象字面量"、对象是【引用类型】(共享,见 00-concepts/value-vs-reference.md)。 +// ⚠️ typeof null 也是 'object' → 那是历史 bug,null 不是对象(见 02 章 §5)。 +// 💡 TS 里对象在【值层面完全一样】,只是多一层:可用 interface/type 描述 +// "这个对象长什么样"(有哪些键、各是什么类型)—— 第 19 章讲,现在知道有这层即可。 +// // 1. 创建 & 结构 // const person = { // name: 'Asabeneh', // 键: 值 @@ -92,6 +109,7 @@ // 这就是后端返回的 JSON、后面高阶函数处理的典型数据。记住"数组套对象"的形状。 // // ✅ 本主题要点回顾 +// 0. 本质:JS 分"原始值 vs 对象"两阵营;数组/函数本质都是对象(能挂属性)⭐⭐ // 1. 对象 = {键: 值} 键值对;表示真实事物 // 2. 取值:.键(固定名)/ [变量](键名是变量)⭐ // 3. 增改直接赋值,删用 delete;是引用类型可原地改