Vue基础教程(16)ECMAScript 6语法之块作用域构造let和const:告别“渣男”var!用let和const让你的Vue代码更靠谱,程序员不再背锅!

兄弟们,敲代码这么多年,你有没有遇到过这种灵异事件?在Vue组件里循环渲染一堆按钮,给每个按钮加点击事件,结果一点击,所有按钮都特么显示最后一个数据!或者明明想定义个固定配置项,一不小心手滑给改了,整个组件直接崩掉…… 别问,问就是“渣男”var在作妖!

没错,那个曾经统治JavaScript变量声明的var,就像个四处留情的海王:没有块级概念,到处泄露变量,还爱“提升”(hoisting)刷存在感。但自从ES6带来了let和const,咱们终于能扬眉吐气,写出更靠谱的Vue代码了!今天,我就用大白话+实战案例,带你彻底搞懂这对“黄金搭档”,保你从此告别背锅侠生涯!


一、var的“渣男”行为大曝光:为啥咱们要甩了它?

先来吐槽下var的几宗罪,看看你是不是也踩过这些坑:

1. 不守边界:缺乏块级作用域

var眼里只有函数作用域,根本不懂什么叫“块”(比如if、for的大括号)。你看这个经典Vue示例:

export default {
  methods: {
    leakyMethod() {
      for (var i = 0; i < 3; i++) {
        // 假装这里有点操作
      }
      console.log(i); // 输出3!i居然泄露到循环外了!
    }
  }
}

循环都结束了,i还能被访问?这好比分手了前任还天天蹲你家门口,瘆得慌!

2. 反复横跳:变量可重复声明

var允许重复声明同一变量,后声明的直接覆盖前面的,团队协作时容易埋雷:

var config = { apiUrl: '/api' };
var config = { timeout: 5000 }; // 队友不小心重名了,第一个config被覆盖!
// 运行时一脸懵:我的apiUrl呢??
3. 玄学“提升”:变量未定义就能用?

var的变量提升(hoisting)特反直觉,比如:

console.log(name); // 不报错,输出undefined!
var name = "小明";

明明还没赋值,却能访问,这种“预判”行为常导致隐蔽bug。

小结:var这些特性在Vue开发中简直是灾难!尤其在处理响应式数据、事件绑定或异步逻辑时,容易造成数据污染或状态错乱。是时候请出咱们的救星——let和const了!


二、let:块级作用域的“专一男友”,Vue循环绑定的神器

let就像个靠谱男友,它的原则是“我的地盘我做主”——严格遵守块级作用域。简单说,用let声明的变量,只在自己所在的{}内有效,出界就失效!

基础用法:

if (true) {
  let blockScoped = "我在块内";
  console.log(blockScoped); // 正常输出
}
console.log(blockScoped); // 报错:blockScoped is not defined

看,变量乖乖待在块里,绝不越界!

Vue实战重点:解决循环事件绑定坑
这是let最香的应用场景!比如渲染列表时,每个按钮需要绑定独立的索引或ID:

<template>
  <div>
    <button v-for="index in 3" :key="index" @click="handleClick(index)">
      按钮{{ index }}
    </button>
  </div>
</template>

<script>
export default {
  methods: {
    handleClick(index) {
      // 若用var,index最终永远是3;用let则正确保留每次循环的值!
      console.log("点击了按钮", index); // 输出1、2、3,精准对应!
    }
  }
}
</script>

底层原理:
每次循环,let都会创建一个新的块级作用域,索引i被“锁”在当前循环内。异步操作(如点击事件)触发时,访问的是当时循环的i值。而var声明的i是全局的,循环结束后i固定为最终值,所有事件都共享它。

技巧延伸:结合Vue的<script setup>使用let管理局部状态:

<script setup>
import { ref } from 'vue';

// 全局状态
const globalCount = ref(0);

// 在函数内用let定义局部变量
const updateCount = () => {
  let localTimer = setTimeout(() => {
    globalCount.value++;
  }, 1000);
  // localTimer只在函数内可用,避免污染全局
};
</script>

三、const:忠贞不渝的“常量老婆”,Vue配置项的守护神

const更狠,它声明的是常量——一旦赋值,绝不允许重新指向新地址(注意:是地址不变,对象内部属性可改,下文细说)。

基础规则:

const PI = 3.14;
PI = 3.14159; // 报错!Assignment to constant variable.

const user = { name: "张三" };
user.name = "李四"; // 允许!因为user指向的地址没变
user = { age: 20 }; // 报错!不能换整个对象!

简单记:const守护的是变量名与内存地址的绑定关系,而非值本身是否可变。

Vue实战重点:锁定配置、防止意外修改
在Vue项目中,常用const定义不可变的配置或引用:

1. API配置:
// config.js
export const API_CONFIG = {
  baseURL: 'https://api.example.com',
  timeout: 5000
};

// Vue组件
import { API_CONFIG } from './config';
export default {
  created() {
    // 放心使用,不怕被手滑覆盖
    axios.get(API_CONFIG.baseURL + '/users');
  }
}
2. Vuex的mutation类型:
// store.js
export const UPDATE_USER = 'UPDATE_USER'; // 用const避免拼写错误导致bug

export default new Vuex.Store({
  mutations: {
    [UPDATE_USER](state, payload) {
      // ...逻辑
    }
  }
});
3. 组合式函数中的固定引用:
<script setup>
import { computed } from 'vue';

const userRoles = ['admin', 'editor'];
// 用const保护计算结果,避免被意外重新赋值
const hasAdminAccess = computed(() => userRoles.includes('admin'));
</script>

常见误区:const声明的对象属性能被修改?
没错!const只保证变量名绑定地址不变。真要冻结对象,需配合Object.freeze()

const frozenConfig = Object.freeze({ version: '1.0' });
frozenConfig.version = '2.0'; // 静默失败(严格模式报错)

四、强强联手:let和const在Vue项目中的最佳实践
1. 默认用const,需要重新赋值再用let

这是行业共识:先用const,发现变量需要变更时再改为let。这样能强制你思考变量是否真的需要改变,减少意外修改。

// 好习惯:默认const
const user = ref(null);
const items = reactive([]);

// 确实需要重赋值时用let
let loading = false;
const fetchData = async () => {
  loading = true; // 允许修改
  // ...请求数据
  loading = false;
};
2. 循环中用let,避免var的陷阱

for循环的索引、for...of的项都建议用let:

// 遍历数组
for (let item of list) {
  setTimeout(() => console.log(item), 100); // 正确输出每个item
}

// 遍历对象键
for (let key in obj) {
  // key每次循环独立绑定
}
3. Vue3组合式API中合理分配

<script setup>中:

  • 用const定义响应式数据(refreactive
  • 用const定义函数、计算属性
  • 用let定义局部临时变量(如计时器ID)
<script setup>
import { ref, onUnmounted } from 'vue';

// const用于响应式数据
const count = ref(0);

// const用于函数
const increment = () => count.value++;

// let用于局部可变状态
let intervalId = null;

onMounted(() => {
  intervalId = setInterval(increment, 1000);
});

onUnmounted(() => {
  clearInterval(intervalId); // 清理作用域内变量
});
</script>

五、面试高频题:let/const的暂时性死区(TDZ)是啥?

这是个常考概念!TDZ指的是:从进入块级作用域,到变量被声明之前的区域,在这访问变量会报错(而var此时是undefined)。

console.log(a); // 报错!TDZ禁止访问
let a = 10;

原理:JS引擎知道块内有let声明,但在执行到声明语句前,不允许访问。这避免了var提升导致的逻辑混乱。

Vue中的提示:在<script setup>中,变量必须先声明后使用,否则直接报错,TDZ机制帮你提前避坑!


总结

兄弟们,let和const不是语法糖,而是代码可靠性的基石!在Vue开发中:

  • let帮你搞定块级作用域,尤其循环绑定、局部状态管理;
  • const守护重要常量,配置项、引用类型再也不怕手滑;
  • 牢记默认const,需改再用let的原则,代码更健壮。

现在就去检查你的Vue项目,把var全替换掉!让咱们告别奇葩bug,早日下班(虽然可能只是换个地方写bug)~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

值引力

持续创作,多谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值