零基础快速入门前端蓝桥杯Web考点深度解析:var、let、const与事件绑定实战(可用于备赛蓝桥杯Web应用开发)

在蓝桥杯 Web 应用开发赛道中,变量声明的特性与 DOM 事件绑定是核心高频考点。本文将结合实战代码,深度解析var、let、const的区别,以及两种事件绑定方案的原理,并对应蓝桥杯考点进行拓展。

一、变量声明:var、let、const 的核心特性

1.1 预解析(变量提升)

核心区别:

  • var 存在变量提升:声明会被提升到作用域顶部,但赋值仍在原地。

  • let/const 不存在变量提升:声明前使用会触发 "暂时性死区"(ReferenceError)。

代码实例:

复制代码
// var 的变量提升
console.log(a, b, c); // 输出:undefined undefined undefined(变量已声明,未赋值)
var a = 'ggx handsome';
var b = 1;
var c = 10;

// let/const 的暂时性死区
// console.log(const1); // 报错:ReferenceError(const1 未初始化)
const const1 = 10; 
console.log(const1); // 输出:10

考点汇总表:

|-----|----------|---------------|
| 特性 | var | let/const |
| 预解析 | ✅ 存在变量提升 | ❌ 不存在(暂时性死区) |

1.2 块级作用域

核心区别:

  • var 无块级作用域:作用域为函数级 或全局 ,{} 无法限制其范围。

  • let/const 有块级作用域:仅在 {} 内有效,可隔离变量。

代码实例:

复制代码
// let 的块级作用域
let a = 10;
console.log(a); // 输出:10(全局作用域)

if (1 > 0) {
    let a = 20; 
    console.log(a); // 输出:20(块级作用域)
}
console.log(a); // 输出:10(全局作用域不受块级影响)

// for 循环中的 let(蓝桥杯高频场景)
for (let i = 0; i < 5; i++) {
    console.log(i); // 输出:0 1 2 3 4(i 仅在循环内有效)
}
// console.log(i); // 报错:i 未定义(块级作用域隔离)

考点汇总表:

|-------|--------------|---------------|
| 特性 | var | let/const |
| 块级作用域 | ❌ 无(函数 / 全局) | ✅ 有({} 内有效) |

1.3 const 的常量特性

const 用于定义常量,核心规则:

  1. 声明时必须赋值(否则报错);

  2. 基本数据类型(如数字、字符串)不可修改;

  3. 引用数据类型(如数组、对象)地址不可改,但内部属性 / 元素可修改。

代码实例:

复制代码
// 1. 声明时必须赋值
// const const2; // 报错:Missing initializer in const declaration
const const2 = 'ggx handsome'; 

// 2. 基本类型不可修改
// const2 = 'ggx really handsome'; // 报错:Assignment to constant variable

// 3. 引用类型:地址不可改,属性/元素可改
const array1 = [1, 2, 3, 4, 5];
const array2 = [1, 2, 3, 4, 5];
console.log(array1 == array2); // 输出:false(地址不同)

array1[0] = 'ggx'; // 修改元素(地址不变)
console.log(array1); // 输出:['ggx', 2, 3, 4, 5]

const obj1 = { name: 'ggx' };
obj1.name = 'ggxC'; // 修改属性(地址不变)
console.log(obj1); // 输出:{ name: 'ggxC' }

考点汇总表:

|----------|-----------------------|
| const 特性 | 规则说明 |
| 声明赋值 | ✅ 必须赋值,否则报错 |
| 基本类型 | ❌ 不可修改值 |
| 引用类型 | ❌ 不可修改地址,✅ 可修改属性 / 元素 |

二、事件绑定的两种方案与蓝桥杯闭包考点

在蓝桥杯 DOM 操作题中,"循环绑定点击事件,获取正确索引" 是经典闭包考点。以下结合代码解析两种方案:

2.1 方案一:var + 自定义属性(ES5 兼容方案)

问题 :var 无块级作用域,循环内的 i 是共享变量 ,循环结束后 i 为最大值(如 5),点击时直接用 i 会出错。

解决 :通过 setAttribute 给每个元素存储索引,点击时用 this.getAttribute('index') 获取。

代码实例:

复制代码
var names = document.querySelectorAll('.name');
var lastIndex = 0;

for (var i = 0; i < names.length; i++) {
    var div = names[i];
    div.setAttribute('index', i); // 存储索引到自定义属性

    div.onclick = function() {
        var index = this.getAttribute('index'); // 获取当前元素的索引
        names[lastIndex].className = 'name'; // 清除上一个高亮
        names[index].className = 'name highLight'; // 当前元素高亮
        lastIndex = index;
        
        console.log(i); // 点击任意元素,输出:5(var 的共享特性)
    };
}

2.2 方案二:let + 块级作用域(ES6 推荐方案)

优势 :let 有块级作用域,每次循环的 i 都是独立变量 ,事件绑定可直接使用 i,无需额外操作 DOM。

代码实例:

复制代码
var names = document.querySelectorAll('.name');
var lastI = 0;

for (let i = 0; i < names.length; i++) {
    names[i].onclick = () => {
        console.log(i); // 点击对应元素,输出:0、1、2...(let 的块级绑定)
        names[lastI].classList.remove('highLight'); // 清除上一个高亮
        names[i].classList.add('highLight'); // 当前元素高亮
        lastI = i;
    };
}

2.3 蓝桥杯考点:闭包与作用域辨析

考点逻辑:

  • var 方案:i 是全局变量,点击事件触发时才读取 i(此时 i 已为循环结束值),需通过自定义属性 "保存" 索引。

  • let 方案:每次循环生成独立的块级作用域,i 被绑定在当前作用域,点击时直接读取作用域内的 i,天然解决闭包问题。

考法示例:

  • 给出 var 循环绑定事件的代码,问点击后输出什么(答案:循环结束值);

  • 要求修复索引错误(方案:改用 let,或用闭包 / 自定义属性)。

三、知识点终极汇总表

3.1 var、let、const 全面对比

|-------|--------------|-------------|---------------------|
| 特性 | var | let | const |
| 预解析 | ✅ 存在变量提升 | ❌ 暂时性死区 | ❌ 暂时性死区 |
| 块级作用域 | ❌ 无(函数 / 全局) | ✅ 有({} 内有效) | ✅ 有({} 内有效) |
| 重新赋值 | ✅ 可以 | ✅ 可以 | ❌ 基本类型不可改,引用类型地址不可改 |
| 声明时赋值 | ✅ 可以不赋值 | ✅ 可以不赋值 | ❌ 必须赋值 |
| 重复声明 | ✅ 同一作用域可重复 | ❌ 同一作用域不可 | ❌ 同一作用域不可 |

3.2 两种事件绑定方案对比

|-----|---------|-----------|-----------|-------|
| 方案 | 变量声明 | 解决方式 | 蓝桥杯适配性 | 代码简洁度 |
| 方案一 | var | 自定义属性存储索引 | ✅ 兼容 ES5 | ⭐⭐ |
| 方案二 | let | 块级作用域绑定索引 | ✅ 推荐(ES6) | ⭐⭐⭐⭐⭐ |

蓝桥杯备考建议:

  • 优先用 let/const 替代 var,避免作用域陷阱;

  • 循环绑定事件时,let 是最简洁的解决方案;

  • 若需兼容 ES5,再考虑自定义属性或闭包。

相关推荐
仿生狮子1 小时前
OpenAI 攻下千禧年难题之后,开发者似乎无动于衷
前端·数学·vibecoding
夏幻灵5 小时前
JavaScript this 面试:五种绑定规则、优先级与常见面试陷阱
开发语言·javascript·面试
Lvan的前端笔记5 小时前
docker:每个前端项目一个 Nginx 容器还是只有一个Nginx容器
前端·nginx·docker
程序猿编码5 小时前
榨干 RTX5090 算力!Qwen3 专用单卡推理引擎,手写C++/CUDA 算子实现 MTP 推测解码
开发语言·c++·大模型推理·qwen3·多模态推理
三天不学习5 小时前
Egg.js 4 突然爆火,原因是否归结于AI 原生落地需求爆发?
前端·javascript·全栈·egg.js
xcs194056 小时前
前端 vue 的前端页面debugger 进不去
前端·javascript·vue.js
bkspiderx6 小时前
Qt 插件机制:动态扩展应用功能的核心框架
开发语言·qt·元数据·qt 插件·qpluginloader
程序员老陆7 小时前
深入理解 C++ thread_local:线程私有存储的正确打开方式
开发语言·c++·程序设计
沐晓时光7 小时前
C语言入门,深入理解指针(3)
c语言·开发语言
明月_清风7 小时前
Deno 终局来了:从挑战 Node 到被 Cloudflare 收编
前端·后端·node.js