前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库函数 name 属性推断规则
JavaScript函数与作用域

匿名函数和箭头函数的 name 是怎么来的?

函数声明和具名函数表达式的 name 就是写的名字。匿名函数和箭头函数没写名字时,如果它被直接赋给一个变量、写在对象字面量的属性上或者作为参数默认值,引擎会把那个变量名或属性名推断成它的 name;其余情况 name 是空字符串。

前端进阶之旅 · 一题精讲更新于 2026.09.29
JavaScript#函数与作用域
先看核心答案读代码示例
理解线索

`name` 的三种来源

  1. 显式名字function foo() {} 和 const a = function foo() {} 都叫 foo
  2. 推断名字匿名函数出现在 const x =、对象字面量属性、默认参数这些位置时,取左边的名字
  3. 包装后的名字bind 返回的函数叫 bound foo,访问器叫 get foo 或 set foo

推断只在函数「定义的那一刻」发生。先定义一个匿名函数,再把它赋给别的变量,名字不会跟着变。

核心回答

先记住这个答案

name 属性主要来自两个地方。一是代码里写明的名字:函数声明 function foo() {},以及具名函数表达式 const a = function foo() {},名字都是 foo。二是引擎推断:匿名函数或箭头函数在定义时就被赋给一个变量、写在对象字面量的属性上、或者作为参数的默认值,引擎会把变量名或属性名设成它的 name。不在这些位置定义的匿名函数,name 是空字符串。bind 返回的函数和 getter、setter 还会带上 bound 、get 、set 这样的前缀。

  • 写了名字就用写的名字,具名表达式也一样
  • 赋给变量或对象字面量属性时自动推断
  • obj.fn = function () {} 这种赋值推断不出名字
  • bind 加 bound 前缀,getter 加 get 前缀

各种写法的 name 对照

把常见写法放在一起打印,规则一眼就能看清。空字符串用 JSON.stringify 包一下,不然打印出来是一个空行。

声明、表达式、箭头、方法、bindJavaScript
function declared() {}
const expression = function () {}
const arrow = () => {}
const obj = { method() {}, get size() { return 1 } }
obj.later = function () {} // 赋值给已有对象的属性
const bound = declared.bind(null)

console.log(declared.name)
console.log(expression.name, arrow.name)
console.log(obj.method.name)
console.log(Object.getOwnPropertyDescriptor(obj, 'size').get.name)
console.log(JSON.stringify(obj.later.name)) // 推断不出来
console.log(bound.name)
console.log(JSON.stringify((() => {}).name)) // 没有任何名字来源
查看输出与解释
declared
expression arrow
method
get size
""
bound declared
""

expression 和 arrow 自己都没写名字,是从 const 左边的变量名推断出来的。对象字面量里的 method() {} 取属性名。getter 的 name 是 get size,要通过属性描述符才能拿到这个函数本身,直接读 obj.size 会触发 getter 返回 1。 最容易被问住的是 obj.later。它明明也是「赋值给一个属性」,name 却是空字符串。原因是推断只在左边是一个变量名,或者在对象字面量、类里定义时发生,obj.later = ... 这种给已有对象的属性赋值不在推断范围内。

推断只发生在定义那一刻

名字是函数被创建时就定下的,之后再怎么赋值都不会改。比如 const a = () => {} 之后再写 const b = a,b.name 还是 'a'。

具名函数表达式的名字优先
const handler = function onClick() {} 这种写法,handler.name 是 'onClick',写明的名字优先于推断。这个名字还有一个作用:它只在函数体内部可见,可以用来递归调用自己,外面改了 handler 变量也不影响递归。
默认参数和解构默认值也会推断
function run(cb = () => {}) {} 里,默认的箭头函数 name 是 'cb'。解构写法 const { onLoad = () => {} } = options 也一样,名字是 'onLoad'。
回答前,多想一步

容易答错的地方

以为匿名函数的 name 一定是空的
只要定义时被赋给变量或写在对象字面量里,就会有名字。现在大部分箭头函数都是 const fn = () => {} 这样定义的,所以它们在调用栈里都能显示出名字。
拿 name 做业务判断或缓存 key
生产构建会压缩变量名,name 可能变成 t、n 这样的单字母。不同函数也可能同名。需要稳定标识时,给函数显式加一个字段,或者直接用函数本身做 Map 的 key。
以为可以直接给 name 赋值
name 是只读的,fn.name = 'x' 不会生效,严格模式下会抛 TypeError。它是可配置的,真要改只能用 Object.defineProperty。
试着用自己的话回答

面试官还会怎么问?

new Function() 创建的函数叫什么?

叫 'anonymous',这是规范里的固定值,和匿名函数表达式的空字符串不一样。

name 有什么实际用处?

主要是调试。报错时的调用栈、性能面板、React DevTools 里显示的组件名都用到它。如果组件直接写成 export default () => {},按规范它的 name 是 'default',DevTools 里看不出是哪个组件,所以很多团队的 lint 规则要求组件必须具名。

类的 name 是什么?

class User {} 的 name 是 'User',匿名类 const Admin = class {} 同样会推断成 'Admin'。如果类里定义了静态方法 static name() {},它会覆盖掉这个属性,User.name 就变成了一个函数。

从一道题,走向一组知识

把知识连起来

函数与作用域

new.target 是什么?在箭头函数里读它会得到什么?

调试构造调用时常打印 new.target.name 看是哪个类进来的,用的就是这里讲的 name。

函数与作用域

对象里写 fn() {} 和 fn: function () {} 有区别吗?

方法简写和 key: function () {} 两种写法得到的 name 一样,区别在 super 和能不能 new。

参考资料

  • JavaScript:函数与作用域参考资料

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 各种写法的 name 对照
  3. 推断只发生在定义那一刻
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑