函数:名称
name
是 Function
实例的一个数据属性,它指示函数在创建时指定的名称,或者对于匿名创建的函数,它可能是 anonymous
或 ''
(空字符串)。
试一试
值
字符串。
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"
初始化程序和默认值
简写方法
const o = {
foo() {},
};
o.foo.name; // "foo";
绑定函数
Function.prototype.bind()
生成一个函数,其名称为“bound ”加上函数名称。
function foo() {}
foo.bind({}).name; // "bound foo"
Getter 和 Setter
类
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 压缩器和缩小器
警告:在使用源代码转换(例如 JavaScript 压缩器(缩小器)或混淆器执行的转换)时,请谨慎使用 name
属性。这些工具通常用作 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' 是 'Foo' 的实例”——而在压缩版本中,其行为有所不同,并进入 else 分支。如果您依赖于 name
属性(如上例所示),请确保您的构建管道不会更改函数名称,或者不要假设函数具有特定的名称。
规范
规范 |
---|
ECMAScript 语言规范 # sec-function-instances-name |
浏览器兼容性
BCD 表仅在启用 JavaScript 的浏览器中加载。