具名函数表达式的函数名是仅在函数内部作用域中声明的局部绑定,不可被外部访问,专用于函数自调用,如const fn = function calc(n) { return n; };中calc仅在函数体内有效。

具名函数表达式的函数名,本质上是一个只在函数内部作用域中声明的局部绑定,不是变量提升出来的全局或外层变量,也不是可被外部引用的标识符。它就像函数体内的一个“私有常量”,专为函数自调用而设。
函数名是作用域内的局部标识符
当你写 const fn = function calc(n) { return n ,<strong>calc</strong> 并非声明在当前作用域(比如全局或块级),而是被 JavaScript 引擎自动注入到该函数的词法环境(Lexical Environment)中,仅对该函数体可见。
- 这个 calc 绑定不可被外部读取:
typeof calc在函数外是"undefined" - 它也不参与变量提升:你不能在函数定义前就使用
calc - 它不能被重新赋值:在函数体内执行
calc = 42不会改变绑定(非严格模式下静默失败,严格模式下报错)
机制源自规范定义,而非语法糖
ECMAScript 标准明确规定:具名函数表达式中的名称,会创建一个不可删除、不可重新绑定的绑定,且该绑定只存在于函数自身的 [[Environment]] 中。这和 let 声明类似,但更严格——它甚至不允许同名 let 或 var 在函数内覆盖它。
- 例如:
function foo() { let foo = 'bar'; }是合法的,内部foo指向的是let声明的变量,原函数名绑定被遮蔽 - 但若写成
const f = function foo() { foo = 123; },赋值无效,foo始终指向函数本身
与函数声明的关键区别
函数声明如 function bar() {} 会触发“函数声明提升”,bar 成为所在作用域的可访问标识符;而具名函数表达式不会提升,它的名字不暴露给外层,只服务自身。
-
function bar() {}→bar在声明前就能调用(提升) -
const x = function bar() {};→bar在任何外部位置都不可访问,包括x所在的作用域 - 即使
x被重赋值或置为null,函数内部的bar()依然能正常递归
实际效果就是“隐形锚点”
这个机制让函数获得了一个稳定、安全、不依赖外部变量的自引用能力。它不污染命名空间,不随外部变量变化而失效,调试时还能显示有意义的函数名——所有这些,都靠那个“进得去、出不来”的内部绑定实现。











