函数声明优先于var变量提升,函数名和函数体均被提升,var仅提升变量名;let/const不提升且有暂时性死区;函数表达式无提升;推荐"use strict"、ESLint规则及统一使用let/const。

函数声明和变量提升不是代码被“挪动”,而是 JavaScript 引擎在创建执行上下文时,把声明登记进作用域内存空间的过程。冲突本身不难处理,关键在于看清谁先登记、谁覆盖谁、什么时候真正可用。
函数声明优先于 var 变量声明
同名时,函数声明会完整提升(函数名 + 函数体),var 声明只提升变量名,赋值留在原处。引擎按顺序处理:先登记函数,再登记 var —— 但若已存在同名函数,var 声明不会重复登记,只等后续赋值来覆盖。
- 结果是:调用发生在赋值前 → 执行函数;赋值后 → 变量生效
- 例如:
foo(); function foo() { console.log(1); } var foo = 2;→ 先输出 1,再让foo变成数字 2 - 反过来:
var foo = 2; foo();→ 报错,因为此时foo是数值,不可调用
避免 var 引发的遮蔽与 undefined 陷阱
函数内部用 var 声明与外层同名变量,会提升至函数顶部并初始化为 undefined,导致访问外层变量失败。
- 比如:
let name = 'Alice'; function test() { console.log(name); var name = 'Bob'; }→ 输出undefined,不是 'Alice' - 解法很直接:用
let或const替代var,它们不提升,且进入暂时性死区(TDZ),提前访问直接报错,反而更容易暴露问题 - 或者统一重命名,比如把函数内变量改成
localName,消除歧义
函数表达式不享受“函数级提升”
const fn = function() {} 或 let fn = () =>{} 属于函数表达式 + 块级绑定,没有提升行为,声明前访问必报 ReferenceError。
- 这比
var的undefined更安全——错误在开发阶段就暴露,而不是运行时悄悄出错 - 推荐写法:
const handleClick = () => { /* ... */ };,语义清晰,无提升风险 - 不要混用:
function handleClick() {}和const handleClick = ...不要同名出现在同一作用域
用工具和习惯加固防线
靠人记规则容易漏,工程化约束更可靠。
- 在文件或函数顶部加
"use strict";,让未声明就赋值的行为直接报错,而不是偷偷创建全局变量 - ESLint 配置
no-var和prefer-const规则,强制使用let/const - 团队约定:顶层作用域禁用
var;函数内变量统一放在顶部声明(即使不用提升,也利于阅读)

















