8

I am creating a JavaScript code and I had a situation where I want to read the object name (string) in the object method. The sample code of what I am trying to achieve is shown below:

// Define my object
var TestObject = function() {
    return {
        getObjectName: function() {
            console.log( /* Get the Object instance name */ );
        }
    };
}

// create instance
var a1 = TestObject();
var a2 = TestObject();

a1.getObjectName(); // Here I want to get the string name "a1";

a2.getObjectName(); // Here I want to get the string name "a2";

I am not sure if this is possible in JavaScript. But in case it is, I would love to hear from you guys how to achieve this.

gyre
  • 16,369
  • 3
  • 37
  • 47
programmer
  • 582
  • 2
  • 4
  • 16
  • 2
    You can't get the name of the variable. There could be multiple variables referring to the same object. You can give the object a `name` property though, and then use `a1.name`. What underlying problem are you trying to solve here? – nnnnnn Mar 18 '17 at 04:05
  • I think you can get an answer here. http://stackoverflow.com/questions/4602141/variable-name-as-a-string-in-javascript – jacob k Mar 18 '17 at 04:08
  • 1
    Your confusion starts with your use of the term "object name". Objects do not have names. They are just values. They may be *held* in a variable, but that variable is not its "name", except informally. –  Mar 18 '17 at 06:18

6 Answers6

11

This is not possible in JavaScript. A variable is just a reference to an object, and the same object can be referenced by multiple variables. There is no way to tell which variable was used to gain access to your object. However, if you pass a name to your constructor function you could return that instead:

// Define my object
function TestObject (name) {
    return {
        getObjectName: function() {
            return name
        }
    };
}

// create instance
var a1 = TestObject('a1')
var a2 = TestObject('a2')

console.log(a1.getObjectName()) //=> 'a1'

console.log(a2.getObjectName()) //=> 'a2'
gyre
  • 16,369
  • 3
  • 37
  • 47
  • 1
    Thanks. I am doing this currently, but wanted to check if there was some way to avoid passing this manually. Thanks for your anwer. :). – programmer Mar 18 '17 at 14:56
0

This is definitely possible but is a bit ugly for obvious reasons. I think this can have some application in debugging. The solution makes use of the ability to get the line number for a code using Error object and then reading the source file to get the identifier.

let fs = require('fs');
class Foo {
    constructor(bar, lineAndFile) {
        this.bar = bar;
        this.lineAndFile = lineAndFile;
    }
    toString() {
        return `${this.bar} ${this.lineAndFile}`
    }
}
let foo = new Foo(5, getLineAndFile());

console.log(foo.toString()); // 5 /Users/XXX/XXX/temp.js:11:22
readIdentifierFromFile(foo.lineAndFile); // let foo

function getErrorObject(){
    try { throw Error('') } catch(err) { return err; }
}

function getLineAndFile() {
    let err = getErrorObject();
    let callerLine = err.stack.split("\n")[4];
    let index = callerLine.indexOf("(");
    return callerLine.slice(index+1, callerLine.length-1);
}

function readIdentifierFromFile(lineAndFile) {
    let file = lineAndFile.split(':')[0];
    let line = lineAndFile.split(':')[1];
    fs.readFile(file, 'utf-8', (err, data) => { 
        if (err) throw err; 
        console.log(data.split('\n')[parseInt(line)-1].split('=')[0].trim());
    }) 
}
Abhas Tandon
  • 1,859
  • 16
  • 26
0

Depending on what your needs are, there are some creative solutions. The main place I want to know a variable name is when I'm debugging.

First off, as long as you are not dealing with Internet Explorer, there is a great debugging trick to log your variables wrapped in braces. The console will show you the details of your "object"... which has only one key, the exact name of your variable!

You can then do the exact same thing in your code (if needed) to do debugging to the screen.

    var isAdmin = true;
    let isDefault = false;
    const isFlubber = null;
    const now = new Date();

    console.log({isAdmin});
    console.log({isDefault});
    console.log({isFlubber});
    console.log({now});
    
    //You can also use console.dir() or console.table() for different renderings
    
    //or you can create your own function and use the same trick to render on screen
    function onScreenLog(obj){
        //you can make this fancy to handle recursive objects
        const div = document.getElementById('onscreen-log');
        for(const [key, value] of Object.entries(obj)){
          div.innerHTML += key + ': <b>' + value + '</b><br/>'; 
        }
    }
    onScreenLog({isAdmin});
    onScreenLog({isDefault});
    onScreenLog({isFlubber});
    onScreenLog({now});
    
<div id="onscreen-log" style="background=color:#fffedf;border:1px solid #ddd;font-family:sans-serif;height:75px;padding:2px;"></div>
scunliffe
  • 62,582
  • 25
  • 126
  • 161
0

Credit goes to this article's author:


// Define my object
function TestObject (name) {
    return {
        getObjectName: function() {
            return name
        }
    };
}

// create instance
const a1 = TestObject('a1')
const a2 = TestObject('a2')

const [a1Name] = Object.keys({a1})
const [a2Name] = Object.keys({a2})

console.log(a1Name) //=> 'a1'

console.log(a2Name) //=> 'a2'
gildniy
  • 3,528
  • 1
  • 33
  • 23
0

When you have such a situation:

 var a={/*...*/};
 var b={property: {/*...*/}}

You could see that, if it is a browser, a, b etc. are all stored in window. However, b.property, an object, is not directly there.

The a and b could be found in case when they are serializable. The built-in window.File (the API), for example, and those like it, are not that, because String(File) gives out a coded reference instead of its contents!

With objects that are serializable, in contexts like browser,

   if((''+obj).startsWith('[Object ')){
      alert('Not serializable'); //later check the same for objects inside of obj;
   }else{;
      for (itr in window) {
        try {
         if (JSON.stringify(window[itr])==JSON.stringify(obj)){
            alert(itr) //return itr
        }
      } catch (err) {} 
   };
0

It is possible if:

  1. Your variables are available in the global space
  2. and redefine TestObject so that it can be instantiated.

// Define my object
function TestObject(){}
TestObject.prototype.getObjectName = function () {
  for (var x in window) {
    try {
      if (window[x] == this) return x;
    } catch (e) {}
  }
};


var a1 = new TestObject();
var a2 = new TestObject();

console.log(a1.getObjectName());
console.log(a2.getObjectName());
customcommander
  • 17,580
  • 5
  • 58
  • 84