Vue3 小白的疑惑:为什么用 const 定义的变量还能改?

明明用const定义了响应式变量(比如const name = ref("小明")),为什么还能通过name.value = "小红"修改它的值?

刚学 Vue3 的小伙伴,大概率会遇到这个 "反常识" 的困惑:

明明用const定义了响应式变量(比如const name = ref("小明")),为什么还能通过name.value = "小红"修改它的值?

要知道在普通 JavaScript 里,const声明的变量可是 "一旦赋值就不能改" 的啊!今天咱们用 5 分钟把这个问题讲透,从此对 Vue3 的响应式不再迷茫。

先搞懂:普通 JS 里的 const 和 let 到底差在哪?

在聊 Vue3 之前,得先回顾下基础 ------ 很多人其实没真正搞懂const的 "不能改" 到底指什么。

比如这段普通 JS 代码:

javascript 复制代码
// 用let声明的变量:可以重新赋值
let userName1 = "小明";
userName1 = "小红"; // 合法,没问题
// 用const声明的变量:不能重新赋值
const userName2 = "小明";
userName2 = "小红"; // 报错!Assignment to constant variable

这里的关键是:const限制的是 "变量的引用",而不是 "变量的值"

如果const声明的是 "引用类型"(比如对象、数组),情况就不一样了:

javascript 复制代码
// const声明对象:变量本身的引用不能改,但对象内部的属性可以改
const user = { name: "小明" };
user.name = "小红"; // 合法!不会报错
user.age = 18;      // 也合法!
// 但不能给user重新赋一个新对象
user = { name: "小刚" }; // 报错!因为改变了变量的引用

对于有 C 语言基础的同学来说,这和指针的逻辑很像:const 修饰的变量就像 const 指针(如 char* const p),指针变量 p 本身存储的内存地址不能改(对应 JS 里变量的引用不能变),但指针指向的内存空间里的数据可以改(对应 JS 里引用类型内部的属性能改)。一句话总结:const就像给变量上了 "锁",但只锁 "变量指向谁",不锁 "指向的内容里有什么"

回到 Vue3:ref 到底做了什么?

理解了普通 JS 的规则,再看 Vue3 的ref就简单了。

当我们写const name = ref("小明")时,Vue3 到底干了什么?

其实ref("小明")会帮我们创建一个 "响应式容器对象" ,你可以把它想象成一个 "装着值的小盒子",结构大概是这样的:

javascript 复制代码
// ref("小明")的本质:返回一个包含value属性的对象
const name = {
  value: "小明" // 我们要修改的,其实是这个盒子里的value
};

所以:

  1. 我们用const声明name,是为了锁定 name 这个 "盒子" 本身------ 不让它被换成其他 "盒子"(比如不能再写name = ref("小刚"));
  1. 而name.value = "小红"修改的是盒子里的内容,并没有改变name指向的 "盒子",这完全符合const的规则。

用一张图更直观:

伪代码 复制代码
const name = ref("小明") → name → [响应式盒子: { value: "小明" }]
name.value = "小红" → name还是指向同一个盒子 → [响应式盒子: { value: "小红" }]
name = ref("小刚") → 试图让name指向新盒子 → 报错!(const不允许)

再延伸:reactive 也是同样的道理吗?

对!reactive虽然不用写.value,但本质和ref一样,都是 "修改对象内部属性"。

比如:

vue 复制代码
const user = reactive({ name: "小明" });
user.name = "小红"; // 合法!修改的是对象内部属性
user = reactive({ name: "小刚" }); // 报错!试图改变user的引用

甚至可以这么理解:ref其实是对reactive的 "封装",帮我们把基本类型(数字、字符串)变成了 "可以被跟踪的对象"。

最后总结:Vue3 里该怎么用 const 和 let?

记住一个核心原则:只要是响应式变量,就用 const;只有非响应式变量需要重新赋值时,才用 let

具体场景:

变量类型 推荐声明方式 原因
ref 创建的变量 const 只改.value,不改变量引用
reactive 创建的变量 const 只改对象内部属性,不改变量引用
非响应式且需要重新赋值的变量 let 比如普通名字切换let tempName = "小明"; tempName = "小红"
函数(方法、钩子) const 函数不需要重新赋值,用 const 更安全

比如正确的写法:

vue 复制代码
<script setup>
// 响应式变量:用const
const name = ref("小明");
const user = reactive({ name: "小明" });
// 方法:用const
const handleRename = () => {
  name.value = "小红"; // 改内部属性,合法
  user.name = "小红"; // 改内部属性,合法
};
// 非响应式且需要改的变量:用let
let tempName = "小明";
const handleTempRename = () => {
  tempName = "小红"; // 需要重新赋值,用let
};
</script>

看到这里,你应该彻底明白为什么 Vue3 里到处都是const了吧?其实不是const"失效" 了,而是我们利用了 "对象引用不变,内部属性可改" 的特性,配合 Vue3 的响应式系统实现了数据更新。

下次再遇到这个疑问,就想想那个 "装值的小盒子"------ 你改的是盒子里的名字,不是盒子本身,所以const当然不会拦着你啦!

相关推荐
_前端小李_2 小时前
关于预检请求
前端
李游Leo2 小时前
JavaScript事件机制与性能优化:防抖 / 节流 / 事件委托 / Passive Event Listeners 全解析
开发语言·javascript·性能优化
扉川川2 小时前
File和Blob对象的区别
javascript
Mintopia2 小时前
在 Next.js 中接入 Google Analytics 与 PostHog —— 一场“数据偷窥”的艺术演出
前端·javascript·next.js
遂心_2 小时前
React useState:20分钟彻底掌握这个让你"状态满满"的Hook
前端·javascript·react.js
月亮慢慢圆2 小时前
Web Animation API
前端
Mintopia2 小时前
AIGC驱动的Web界面设计:技术逻辑与用户体验平衡
前端·javascript·aigc
盏茶作酒292 小时前
浅拷贝和深拷贝
前端·javascript
在掘金801102 小时前
pm2 程序 windows开机启动管理设置
前端