By Axel Rauschmayer

The name property of a function contains its name:

    > function foo() {}

This property is useful for debugging (its value shows up in stack traces) and some metaprogramming tasks (picking a function by name etc.).

Prior to ECMAScript 6 (ES6), this property was already supported by most engines. With ES6, it becomes part of the language standard and is frequently filled in automatically.

The following sections describe how name is set up automatically for various programming constructs.


Functions pick up names if they are created via variable declarations:

    let func1 = function () {};
    console.log(; // func1
    const func2 = function () {};
    console.log(; // func2
    var func3 = function () {};
    console.log(; // func3

But even with a normal assignment, name is set up properly:

    let func4;
    func4 = function () {};
    console.log(; // func4
    var func5;
    func5 = function () {};
    console.log(; // func5

With regard to names, arrow functions are like anonymous function expressions:

    const func = () => {};
    console.log(; // func

From now on, whenever you see an anonymous function expression, you can assume that an arrow function works the same way.

Default values

If a function is a default value, it gets its name from its variable or parameter:

    let [func1 = function () {}] = [];
    console.log(; // func1
    let { f2: func2 = function () {} } = {};
    console.log(; // func2
    function g(func3 = function () {}) {
    console.log(g()); // func3

Methods in object literals

If a function is the value of a property, it gets its name from that property. It doesn’t matter if that happens via a method definition (line A), a traditional property definition (line B), a property definition with a computed property key (line C) or a property value shorthand (line D).

    function func() {}
    let obj = {
        m1() {}, // (A)
        m2: function () {}, // (B)
        ['m' + '3']: function () {}, // (C)
        func, // (D)
    console.log(; // m1
    console.log(; // m2
    console.log(; // m3
    console.log(; // func

The names of getters are prefixed with 'get', the names of setters are prefixed with 'set':

    let obj = {
        get foo() {},
        set bar(value) {},
    let getter = Object.getOwnPropertyDescriptor(obj, 'foo').get;
    console.log(; // 'get foo'
    let setter = Object.getOwnPropertyDescriptor(obj, 'bar').set;
    console.log(; // 'set bar'

Methods in class definitions

The naming of methods in class definitions is similar to object literals:

    class C {
        m1() {}
        ['m' + '2']() {} // computed property key
        static classMethod() {}
    console.log(; // m1
    console.log(new C(); // m1
    console.log(; // m2
    console.log(; // classMethod

Getters and setters again have the name prefixes 'get' and 'set', respectively:

    class C {
        get foo() {}
        set bar(value) {}
    let getter = Object.getOwnPropertyDescriptor(C.prototype, 'foo').get;
    console.log(; // 'get foo'
    let setter = Object.getOwnPropertyDescriptor(C.prototype, 'bar').set;
    console.log(; // 'set bar'

Named function definitions

This scenario has always been well supported: a function definition with a name passes it on to the name property.

For example, a function declaration:

    function foo() {}
    console.log(; // foo

The name of a named function expression also sets up the name property.

    const bar = function baz() {};
    console.log(; // baz

Because it comes first, the function expression’s name baz takes precedence over other names (e.g. the name bar provided via the variable declaration):

However, as has in ES5, the name of a function expression is only a variable inside the function expression:

    const bar = function baz() {
        console.log(; // baz
    console.log(baz); // ReferenceError

Class definitions

Remember that class definitions create functions. Those functions also have their property name set up correctly:

    class Foo {}
    console.log(; // Foo
    const Bar = class {};
    console.log(; // Bar

Default exports

All of the following statements set name to 'default':

    export default function () {}
    export default (function () {});
    export default class {}
    export default (class {});
    export default () => {};

Other programming constructs

  • Generator functions and generator methods get their names the same way that normal functions and methods do.

  • new Function() produces functions whose name is 'anonymous'. A webkit bug describes why that is necessary on the web.

  • Function.prototype.bind() produces functions whose name is 'bound'.

Methods whose keys are symbols

In ES6, the key of a method can be a symbol. The name property of such a method is still a string:

  • If the symbol has a description, the method’s name is the description in square brackets.
  • Otherwise, the method’s name is the empty string ('').
    const key1 = Symbol('description');
    const key2 = Symbol();
    let obj = {
        [key1]() {},
        [key2]() {},
    console.log(obj[key1].name); // '[description]'
    console.log(obj[key2].name); // ''

Property name is only created automatically, never updated

Assignment etc. only set the name if that property doesn’t exist, yet. Accordingly, anonymous function expressions and arrow functions don’t initially have it:

    > 'name' in (function () {})
    > 'name' in (() => {})

The function property name in the spec

  • The spec operation SetFunctionName() sets up the property name. Search for its name in the spec to find out where that happens.
  • Anonymous function expressions not having a property name can be seen by looking at their runtime semantics:
    • The names of named function expressions are set up via SetFunctionName(). That operation is not invoked for anonymous function expressions.
    • The names of function declarations are set up when entering a scope (they are hoisted!).
  • When an arrow function is created, no name is set up, either (SetFunctionName() is not invoked).

Suport for the name property in engines

In Kangax’ ES6 table, you can see that no engine currently fully supports name, not even Babel. Thus, the code in this blog post shows how things should be, not how they are in any single engine.

Source:: 2ality