# 通用概念 · 值 vs 引用(value vs reference)⭐⭐ > 跨主题核心概念。函数传参、对象、数组章都会反复用到。JS 最重要的底层认知之一。 ## 一、两大阵营 | | 原始值(primitive) | 引用类型(reference) | |---|---|---| | 有哪些 | `number` `string` `boolean` `undefined` `null` `bigint` `symbol` | `object` `array` `function` | | 变量里存的 | **值本身** | 指向对象的**地址(引用)** | | 赋值给别人时 | **复制一份副本** | **共享同一个对象** | | 能原地改内部吗 | ❌ 不可变 | ✅ 可以 | **一句话:原始值"复制",引用类型"共享"。** ## 二、决定性证据:改一个,另一个变不变? ### 原始值 → 复制副本,各改各的 ```js let a = 'hello' let b = a // b 拿到的是【副本】 a = 'world' // 改 a console.log(b) // 'hello' ← b 没变! ``` ### 引用类型 → 共享同一个,牵一发动全身 ```js let x = [1, 2, 3] let y = x // x 和 y 指向【同一个】数组 x[0] = 99 // 改 x console.log(y) // [99, 2, 3] ← y 跟着变了! ``` > 这就是分水岭:值类型复制、互不影响;引用类型共享、一改都变。 ## 三、字符串不可变:`word[0] = 'Y'` 会怎样 字符串是**原始值**,不是对象,没有"内部格子供你寻址修改"。 ```js let word = 'hello' word[0] = 'Y' // 静默无效(严格模式下报错) console.log(word) // 'hello' ← 没变! ``` - **能读不能写**:`word[0]` 读字符 OK,但赋值无效 - `word[0]` 读出来的是**复制的值** `'h'`,和 word 内部已无关系 —— 不通向本体 - 严格模式(`'use strict'`)下会报 `TypeError: Cannot assign to read only property` **想"改"字符串 → 造个新的再赋值回去:** ```js let word = 'hello' word = 'Y' + word.slice(1) // 'Y' + 'ello' console.log(word) // 'Yello' ``` (这正是 04-strings D 题"首字母大写"的原理:新字符 + 剩余,再赋值) ## 四、对比:数组可以原地改 长得像(都用 `[0]`),行为相反: ```js let arr = [1, 2, 3] arr[0] = 99 // ✅ 数组是引用类型 → 通向对象内部 → 改得动 console.log(arr) // [99, 2, 3] let str = 'abc' str[0] = 'X' // ❌ 字符串不可变 → 无效 console.log(str) // 'abc' ``` ## 五、为什么这很重要(伏笔) - **函数传参**:传原始值 = 传副本(函数内改不动外面);传对象 = 传引用(函数内能改到外面的对象) - **复制对象/数组**:`let b = a` 只是共享,不是真复制;要真复制得用别的手段(后面学) - 很多"我明明没改它怎么变了"的 bug,根源都是引用共享 --- ## ✅ 一句话记死 > **原始值(含字符串)= 复制的值,不可变,`[0]` 只能读;引用类型(对象/数组)= 共享的地址,可原地改,`[0]` 通向本体。**