具名函数表达式的“内部名称”仅在函数体内有效,不参与外部作用域变量管理,外部赋值、重声明或删除均无效;它是函数作用域的固有属性。

具名函数表达式(Named Function Expression)的“内部名称”不是变量,而是一个只在函数体内部生效的绑定标识符。它不参与外部作用域的变量管理,因此外部赋值、重声明或删除操作完全不影响它。
内部名称是函数作用域的固有属性
当你写 const fn = function calc(n) { return n ,<strong>calc</strong> 并非一个可被外部读取或修改的变量,而是 JavaScript 引擎为该函数自动创建的一个“词法绑定”——类似函数参数或 <code>let 声明的局部名,仅存在于函数自身的词法环境(Lexical Environment)中。
- 它不会出现在外层作用域中:
console.log(calc);直接报错ReferenceError - 即使你执行
fn = null;或const fn = 'oops';,函数体内对calc的调用依然有效 - 这个绑定在函数创建时就已固化,运行时不可重新赋值(尝试
calc = 42会报TypeError)
它和外部变量名完全解耦
外部变量(如 fn)只是指向该函数对象的一个引用,就像给一个人起个外号;而 calc 是函数自己“认得自己”的名字,不依赖任何外号。
- 你可以把同一个函数赋给多个变量:
const a = fn; const b = fn;,递归仍靠calc,与a或b无关 - 甚至把函数传入另一个作用域:
someCallback(fn),只要函数体没被改写,calc就始终可用 - 这不同于匿名函数依赖
arguments.callee(已禁用)或外部变量名(如fn(n-1)),后者一旦引用断开就失效
调试与堆栈也印证它的独立性
浏览器开发者工具中,调用栈显示的是 calc,而不是 anonymous 或变量名 fn。这意味着引擎在执行时,识别的是函数自身的内部名称,而非它被挂在哪条变量链上。
- 错误堆栈里反复出现
calc@xxx.js:5:12,说明它是运行时真实存在的调用节点 - 断点停在递归中间层时,作用域面板里能清楚看到
calc绑定着当前函数对象,且不可编辑 - 这种稳定性,正是它能在闭包、高阶函数、记忆化等复杂场景中可靠工作的底层依据
不复杂但容易忽略:名字一旦写在 function 关键字之后,它就属于函数自己,不是你代码里的“公共财产”。











