Javascript ES6 - get name of instance from within class

1.3k views Asked by At

I'd like to be able to get the name of the instance that instantiated a class, from within the class.

Example:

class MyClass {
    getInstanceName() {
        // code that figures out the name given to the instance 
        // instantiating this class
    }
}

var inst = new MyClass();
console.log(inst.getInstanceName()); // should log "inst"

I'd like to get this to emit an event from within the class with the instance name. I'm doing this in node.js

1

There are 1 answers

0
jfriend00 On BEST ANSWER

I'd like to be able to get the name of the variable the instance was assigned to, from within the class.

This is not something that is possible in Javascript.

An object can be assigned to hundreds of variables. Only the internals of the language implementation (such info used by the garbage collector) knows what variables contain a reference to a given object. That is not information that is made available to users of the language.

If, in your circumstance, you wanted an object to store info like this, you'd have to pass in the name to the constructor yourself. And, then the object's constructor could save that string to be provided later when the getInstanceName() method was called. There is no way to do this automatically.

Here's a simple implementation of the constructor storing the name.

var inst = new MyClass("inst");

class MyClass {
    constructor(name) {
        this._name = name;
    }
    getInstanceName() {
        return this._name;
    }
}

Or, a non-settable, non-enumerable property:

class MyClass {
    constructor(name) {
        Object.defineProperty(this, "_name", {
            configurable: false,
            enumerable: false,
            value: name,
            writable: false
        });
    }
    getInstanceName() {
        return this._name;
    }
}

Which could be shortened to this:

class MyClass {
    constructor(name) {
        Object.defineProperty(this, "_name", {value: name});
    }
    getInstanceName() {
        return this._name;
    }
}

because configurable, enumerable and writable all default to false when you use Object.defineProperty().


Or, if you wanted to not use an accessible property on the object, you could make it private by doing this:

const MyClass = (function() {
    // keep track of names in a private space
    const names = new WeakMap();


    class MyClass {
        constructor(name) {
            names.set(this, name);
        }
        getInstanceName() {
            return names.get(this);
        }
    }
    return MyClass;
})();

var inst = new MyClass("inst");

As an example of multiple variables containing the same reference, look at this:

var x, y, z;
x = y = z = new MyClass();

Now, you have three separate variables, all with a reference to the same object. So, even if the language wanted to do what you asked (which it doesn't), there is no canonical variable that contains a reference to a given object.

Or, this:

function doSomething(obj) {
   var t = obj;
   // at this point, there are 5 separate variables with a reference to your object
}

var x, y, z;
x = y = z = new MyClass();

doSomething(x);

Which has 5 separate references to the same object. There is no canonical variable.