You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于JavaScript同文件中块级作用域内函数声明未被后续同名函数覆盖的原因咨询

关于JavaScript同文件中块级作用域内函数声明未被后续同名函数覆盖的原因咨询

你这次遇到的现象确实是个容易踩的JS细节坑,先把你最后那段关键测试代码清晰列出来,方便咱们拆解:

{
  function testing() {
    console.log("does it show in the console");
  }
}
testing()
setTimeout(()=> testing(), 3000)
function testing() {
  console.log("this will override it");
}
testing()

按照你之前的经验,原本以为后面的全局testing函数声明会覆盖前面块内的,结果三次输出全是块内函数的内容——这其实是非严格模式下块级函数声明的特殊提升+执行时序规则在搞鬼,咱们一步步捋清楚:

1. 先看执行前的「提升」隐藏操作

JS引擎在真正执行代码前,会先做「提升(Hoisting)」处理,这一步是后台偷偷完成的:

  • 对于你写在块外面的全局函数声明:会直接把整个函数定义提升到全局作用域的最顶部,此时全局变量testing指向这个输出“override”的函数。
  • 对于你写在{}里的非严格模式块级函数声明:引擎会先在全局作用域创建一个名为testing的变量,但初始值是undefined;而这个函数的实际定义只会提升到块的顶部,不会直接到全局。

2. 按执行顺序看变量的变化

提升完成后,代码开始从上到下执行,这里的关键时序是:

  1. 执行块{ ... }:非严格模式下的特殊规则生效——块内的testing函数会被赋值给全局的testing变量。这一步直接把全局testing从之前指向的“override”函数,替换成了块内的“does it show...”函数。
  2. 执行第一个testing():此时全局testing已经被块内函数覆盖,所以输出“does it show in the console”。
  3. 执行setTimeout:定时器回调会在3秒后执行,但此时全局testing的值已经是块内函数,所以3秒后调用的还是它。
  4. 跳过后面的全局函数声明:划重点!这个函数声明在提升阶段已经处理过了,执行阶段不会再重新赋值testing变量。所以这行代码在执行时,完全不会改动testing的指向。
  5. 执行最后一个testing():全局testing依然指向块内函数,输出同样内容。

验证:开启严格模式试试

如果你在代码最顶部加上'use strict';开启严格模式,块级函数的行为就会符合你更直觉的预期:块内的testing函数只会被限制在块内部,不会污染全局作用域。此时执行代码,三次输出都会是后面全局函数的“this will override it”——因为严格模式下,块级函数不会跨块提升和赋值,完全符合你最初的预期。

这次的核心收获

  • 非严格模式下的块级函数是个“历史遗留特例”,提升阶段占坑、执行阶段赋值的逻辑很反直觉;
  • 全局函数声明的提升是一次性的,执行阶段不会重复覆盖变量。

建议日常写JS时尽量开启严格模式,能大幅减少这种“意外”的特殊行为,让代码逻辑更可控~

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 08:58:09