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.
2.7 KiB
2.7 KiB
通用概念 · 值 vs 引用(value vs reference)⭐⭐
跨主题核心概念。函数传参、对象、数组章都会反复用到。JS 最重要的底层认知之一。
一、两大阵营
| 原始值(primitive) | 引用类型(reference) | |
|---|---|---|
| 有哪些 | number string boolean undefined null bigint symbol |
object array function |
| 变量里存的 | 值本身 | 指向对象的地址(引用) |
| 赋值给别人时 | 复制一份副本 | 共享同一个对象 |
| 能原地改内部吗 | ❌ 不可变 | ✅ 可以 |
一句话:原始值"复制",引用类型"共享"。
二、决定性证据:改一个,另一个变不变?
原始值 → 复制副本,各改各的
let a = 'hello'
let b = a // b 拿到的是【副本】
a = 'world' // 改 a
console.log(b) // 'hello' ← b 没变!
引用类型 → 共享同一个,牵一发动全身
let x = [1, 2, 3]
let y = x // x 和 y 指向【同一个】数组
x[0] = 99 // 改 x
console.log(y) // [99, 2, 3] ← y 跟着变了!
这就是分水岭:值类型复制、互不影响;引用类型共享、一改都变。
三、字符串不可变:word[0] = 'Y' 会怎样
字符串是原始值,不是对象,没有"内部格子供你寻址修改"。
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
想"改"字符串 → 造个新的再赋值回去:
let word = 'hello'
word = 'Y' + word.slice(1) // 'Y' + 'ello'
console.log(word) // 'Yello'
(这正是 04-strings D 题"首字母大写"的原理:新字符 + 剩余,再赋值)
四、对比:数组可以原地改
长得像(都用 [0]),行为相反:
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]通向本体。