Function.prototype.name
Returns the function's name, inferred from its declaration or assignment position.
func.name- Added in JavaScript ECMAScript 2015 (standardized; widely implemented as a non-standard extension before then)
Return value
stringThe function's name as specified when it was created, or "anonymous" or "" (an empty string) for functions created anonymously.
Errors
Assigning to name throws a TypeError in strict mode because the property is not writable; use Object.defineProperty() instead.
Changelog
- PHP ECMAScript 2015Name inference was standardized: anonymous functions assigned to a variable, property, class field or destructuring default now take the name of the binding instead of an empty string.
- PHP ECMAScript 2015name became configurable: true. In non-standard pre-ES2015 implementations the configurable attribute was false as well, so it could not be redefined.
- PHP ECMAScript 2015Bound functions gained the "bound " prefix, getters and setters gained "get "/"set ", and symbol-keyed methods take the symbol description in square brackets.
name is a read-only, non-enumerable, configurable string used by stack traces, error messages and debuggers. It has no semantic significance to the language itself — nothing behaves differently because of it.
Where the name comes from
- Declarations and named expressions use the written identifier.
- Anonymous functions take the name of the binding they are assigned to at creation:
const f = () => {}gives"f",{ prop: function () {} }gives"prop". - Prefixes are added for bound functions (
"bound foo"), getters ("get foo") and setters ("set foo"). - Function() produces
"anonymous"; a truly anonymous expression not assigned anywhere produces"".
What trips people up
Inference is syntactic and one-shot. It happens only when the function literal is directly on the right of an assignment or in a property definition. Pass the same literal through a wrapper, put it in an array, or return it from a factory and the name stays empty — which is why callbacks so often show as <anonymous> in stack traces.
Also, later reassignment does not rename anything: the name is captured once, when the function object is created.
Example
When to use it
- Label a callback in a log line or custom error message
- Show the constructor name of a value with value.constructor.name
- Detect in a plugin system that a required hook is an anonymous function
- Build a registry keyed by the names of the handler functions passed in
Frequently asked questions
Why is my function's name an empty string?
Because the function literal was not in a position where a name could be inferred — it was passed straight as an argument, stored in an array, or returned from a factory. Give it an explicit name (function handler() {} or const handler = () => {}) so it shows up in stack traces.
Can I rename a function?
Not by assignment, since name is not writable, but yes with Object.defineProperty(fn, "name", { value: "newName" }) because the property is configurable. This is standard practice for decorators and wrappers that should not obscure the original name.
Why does my bound function's name start with "bound"?
The specification requires the bound function's name to be the target's name with a "bound " prefix, so foo.bind(obj).name is "bound foo". It is a debugging aid; nothing about the function's behaviour depends on it.
More examples
Prefixes, symbols and classes
Accessors are named "get width" and "set width", and a symbol-keyed method takes its symbol description in brackets: "[size]". Classes follow the same rules as function declarations, which is what makes value.constructor.name a usable runtime type label.
const sym = Symbol("size");
const o = {
get width() { return 1; },
set width(v) {},
[sym]() {},
};
const d = Object.getOwnPropertyDescriptor(o, "width");
console.log(d.get.name, "|", d.set.name, "|", o[sym].name);
class Shape { static make() {} }
console.log(Shape.name, Shape.make.name);
console.log(new Shape().constructor.name);name is read-only but configurable
Plain assignment fails: it throws in strict mode and is silently ignored otherwise, so the name is unchanged. Because the property is configurable, defineProperty succeeds — the technique wrapper libraries use so a wrapper reports the wrapped function's name.
function original() {}
try {
original.name = "renamed";
} catch {
console.log("assignment rejected in strict mode");
}
console.log(original.name);
Object.defineProperty(original, "name", { value: "renamed" });
console.log(original.name);
Discussion