Javascript class names

Since javascript classes are just functions they have a name property, but it's probably best not to use it.

Javascript functions have a name property but the way it is derived is complicated enough that it's not usually sensible to depend on it. On the other hand, debugging and logging tools often display the name property of an object's constructor function, so one scenario where it might be useful to know just a bit about this property is when dynamically generating classes.

The MDN web docs do a good job of summarising the various ways it is assigned a value in the ES2015 spec so if you do plan to use this in anger then take the time to read those (28 mentions of SetFunctionName in the spec!).

Static names

Usually the name of the class will be set at design time.

A class can (and usually should!) be given a name explicitly:

// Static name, known at design time
class Foo { }

// Foo.name === 'Foo'

Or it can be inferred from the property it's assigned to:

const temp = {
    Foo: class {}
};

const Foo = temp.Foo;
// Foo.name === 'Foo'

The limitation in both of these that the class will always have the same name, Foo, even if you create it at run time:

function defineClass() {
    return class Foo { };
}

const Class1 = defineClass();
const Class2 = defineClass();
// Class1.name === 'Foo'
// Class2.name === 'Foo'

Dynamic names

If you'd like to create classes with different names at run time then the following two techniques can help.

You can explicitly supply a name getter on the class:

// Dynamic name, set by explicit name property at run time
function defineClassWithExplicitName(name) {
  return class {
    static get name() { return name; }
  };
}

const Class1 = defineClassWithExplicitName('Foo');
const Class2 = defineClassWithExplicitName('Bar');
// Class1.name === 'Foo';
// Class2.name === 'Bar';

Or you can use dynamic property syntax ({ [propName]: ... }) to control the inferred function name:

// Dynamic name, inferred at run time
function defineClassWithInferredName(name) {
  const temp = {
    [name]: class { },
  };
  return temp[name];
}

const Class1 = defineClassWithInferredName('Foo');
const Class2 = defineClassWithInferredName('Bar');
// Class1.name === 'Foo';
// Class2.name === 'Bar';
Published on: 12 Sep 2017