Function: name
Function 实例的 name 数据属性指示函数创建时指定的函数名,或者对于匿名创建的函数,它可能是 anonymous 或 ''(空字符串)。
试一试
const func1 = function () {};
const object = {
func2: function () {},
};
console.log(func1.name);
// Expected output: "func1"
console.log(object.func2.name);
// Expected output: "func2"
值
字符串。
Function: name 的属性属性 | |
|---|---|
| 可写 | 否 |
| 可枚举 | 否 |
| 可配置 | 是 |
注意: 在非标准、ES2015 之前的实现中,configurable 属性也为 false。
描述
函数的 name 属性可用于在调试工具或错误消息中标识函数。它对语言本身没有语义意义。
name 属性是只读的,不能通过赋值运算符更改。
function someFunction() {}
someFunction.name = "otherFunction";
console.log(someFunction.name); // someFunction
要更改它,请使用 Object.defineProperty()。
name 属性通常根据函数的定义方式来推断。在接下来的部分中,我们将描述推断它的各种方式。
函数声明
name 属性返回函数声明的名称。
function doSomething() {}
doSomething.name; // "doSomething"
默认导出的函数声明
export default 声明将函数作为声明而不是表达式导出。如果声明是匿名的,则名称为 "default"。
// -- someModule.js --
export default function () {}
// -- main.js --
import someModule from "./someModule.js";
someModule.name; // "default"
函数构造函数
使用 Function() 构造函数创建的函数名称为 "anonymous"。
new Function().name; // "anonymous"
函数表达式
如果函数表达式有名称,则该名称用作 name 属性。
const someFunction = function someFunctionName() {};
someFunction.name; // "someFunctionName"
使用 function 关键字或箭头函数语法创建的匿名函数表达式,默认名称为 ""(空字符串)。
(function () {}).name; // ""
(() => {}).name; // ""
然而,这种情况很少见 — 通常,为了在其他地方调用该函数,函数表达式会与一个标识符关联。匿名函数表达式的名称可以在某些语法上下文中推断出来,包括: 变量声明、方法、 初始化程序和默认值。
无法推断名称的一个实际场景是函数从另一个函数返回
function getFoo() {
return () => {};
}
getFoo().name; // ""
变量声明和方法
变量和方法可以从其语法位置推断匿名函数的名称。
const f = function () {};
const object = {
someMethod: function () {},
};
console.log(f.name); // "f"
console.log(object.someMethod.name); // "someMethod"
赋值也同样适用
let f;
f = () => {};
f.name; // "f"
初始化程序和默认值
在 解构、 默认参数、 类字段 等的初始化程序(默认值)中的函数将继承绑定标识符的名称作为它们的 name。
const [f = () => {}] = [];
f.name; // "f"
const { someMethod: m = () => {} } = {};
m.name; // "m"
function foo(f = () => {}) {
console.log(f.name);
}
foo(); // "f"
class Foo {
static someMethod = () => {};
}
Foo.someMethod.name; // someMethod
简写方法
const o = {
foo() {},
};
o.foo.name; // "foo";
绑定函数
Function.prototype.bind() 会生成一个函数,其名称是 "bound " 加上函数名。
function foo() {}
foo.bind({}).name; // "bound foo"
Getter 和 setter
使用 get 和 set 访问器属性时,函数名称中会出现 "get" 或 "set"。
const o = {
get foo() {
return 1;
},
set foo(x) {},
};
const descriptor = Object.getOwnPropertyDescriptor(o, "foo");
descriptor.get.name; // "get foo"
descriptor.set.name; // "set foo";
类
类的名称遵循与函数声明和表达式相同的算法。
class Foo {}
Foo.name; // "Foo"
Symbol 作为函数名
如果 Symbol 用作函数名且该 Symbol 有描述,则方法的名称是方括号中的描述。
const sym1 = Symbol("foo");
const sym2 = Symbol();
const o = {
[sym1]() {},
[sym2]() {},
};
o[sym1].name; // "[foo]"
o[sym2].name; // "[]"
私有字段和方法
私有字段和私有方法将哈希(#)作为其名称的一部分。
class Foo {
#field = () => {};
#method() {}
getNames() {
console.log(this.#field.name);
console.log(this.#method.name);
}
}
new Foo().getNames();
// "#field"
// "#method"
示例
获取对象的构造函数名
您可以使用 obj.constructor.name 来检查对象的 "类"。
function Foo() {} // Or: class Foo {}
const fooInstance = new Foo();
console.log(fooInstance.constructor.name); // "Foo"
但是,由于静态成员会成为类的自有属性,因此我们无法获取几乎所有具有静态方法属性 name() 的类的类名。
class Foo {
constructor() {}
static name() {}
}
有了 static name() 方法后,Foo.name 不再持有实际的类名,而是指向 name() 函数对象。尝试通过 fooInstance.constructor.name 获取 fooInstance 的类,将根本无法得到类名,而是得到一个指向静态类方法的引用。示例
const fooInstance = new Foo();
console.log(fooInstance.constructor.name); // ƒ name() {}
由于静态字段的存在,name 可能也不是一个函数。
class Foo {
static name = 123;
}
console.log(new Foo().constructor.name); // 123
如果一个类有一个名为 name 的静态属性,它也会变得可写。在没有自定义静态定义的情况下,内置定义是只读的。
Foo.name = "Hello";
console.log(Foo.name); // "Hello" if class Foo has a static "name" property, but "Foo" if not.
因此,您不能依赖内置的 name 属性来始终保存类的名称。
JavaScript 压缩器和最小化器
警告: 使用 name 属性进行源代码转换时要小心,例如 JavaScript 压缩器(最小化器)或混淆器进行的转换。这些工具通常作为 JavaScript 构建管道的一部分,在部署到生产环境之前减小程序的大小。此类转换通常会在构建时更改函数的名称。
源代码,例如
function Foo() {}
const foo = new Foo();
if (foo.constructor.name === "Foo") {
console.log("'foo' is an instance of 'Foo'");
} else {
console.log("Oops!");
}
可能会被压缩为
function a() {}
const b = new a();
if (b.constructor.name === "Foo") {
console.log("'foo' is an instance of 'Foo'");
} else {
console.log("Oops!");
}
在未压缩的版本中,程序会进入真值分支并记录 "'foo' is an instance of 'Foo'" — 而在压缩版本中,它的行为不同,会进入 else 分支。如果您依赖 name 属性,就像上面的示例一样,请确保您的构建管道不会更改函数名称,或者不要假设函数具有特定的名称。
规范
| 规范 |
|---|
| ECMAScript® 2026 语言规范 # sec-function-instances-name |
浏览器兼容性
加载中…