Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I set the JavaScript object name that gets returned in a console.log?

So, first question here - please be gentle.

I'm working on a fairly JavaScript heavy project with a few other developers from various non-web programming backgrounds and we've decided to try and use public and private methods and properties in our JavaScript psuedo-classes purely as a good coding practice (ie. we know theres no actual advantage or security in it)

We've toyed with a few different ways of doing public & private (ie. using locally scoped variables and functions with privileged methods for public consumption) and we've currently settled on having our JavaScript class constructors actually return an object that represents only their public interface, effectively hiding everything else.

Here's an example:

function MyObject()
 {
  var _this = this;

  this._privateProperty = 'somevalue';

  this._privateMethod = function()
  {
   // Do Something
  }

  this.public = 
  {
   publicProperty : _this._privateProperty,
   publicMethod : function(){ return _this.privateMethod() }
  }

  return this.public;
 }

Which when instantiated and logged in Chrome:

 var obj = new MyObject();
 console.log(obj);

Outputs:

> Object
    > publicMethod: function (){ return _this.privateMethod() }
    > publicProperty: "somevalue"
    >__proto__: Object

Now to my question: Because were returning the public interface from the constructor as new object, when you console.log you'll notice that it identifies itself as > Object - whereas if we don't return that public interface it is identified as > MyObject.

Ideally, we'd like to have the latter displayed for debugging purposes and I know how to access the "MyObject" name of the contstructor with _this.constructor.name, but have no idea how to set it so its recognized that way.

Does anyone know how to manually set this?

Note:
I know this is in some ways a bastardization of JavaScript convention and trying to fit a square peg in a round hole, but we found it to be a very obvious and readable way to accomplish what we were trying to do. I'm open to suggestions on how to accomplish this with a different design, but I'm ultimately looking for an answer that fits our current design.

like image 397
drewdah Avatar asked Jan 27 '11 21:01

drewdah


People also ask

Can you console log an object in JavaScript?

You can use the console. log() method, if you simply wants to know what's inside an object for debugging purpose. This method will print the object in browser console.

How do you name a variable in a console log?

There is no way to get the name of a variable inside of your log function. You can only do it inside of the caller of your log function, by converting the calling function to a string and parsing the code and grabbing the variable name passed to your log function.


3 Answers

You should be able to set the 'toString' function of the obj. E.g.

obj.constructor.prototype.toString = function() { return "MyObject"; }

This will make the console.log display 'MyObject' instead of Object.

like image 148
cellcortex Avatar answered Sep 22 '22 13:09

cellcortex


Despite the valiant efforts of my team members and the very helpful users of this site who offered solutions we've decided that this design is ultimately unmaintainable and have instead opted for a design that is a little less obvious, but achieves the same result.

function MyObject()
{
    var _privateProperty = 'somevalue';

    function _privateMethod()
    {
        // Do Something
    }

    // Public Interface
    this.publicProperty = _privateProperty;
    this.publicMethod = _privateMethod; 

}

With this approach we are basically making EVERY property and method private by default, and at the bottom of our "classes" we expose the ones we want available publicly. I think most would agree that this follows the normal JavaScript convention better than our initial design, which hopefully means it will be easier to read and maintain for others.

Thanks again for those who took the time to try a come up with a solution.

like image 35
drewdah Avatar answered Sep 18 '22 13:09

drewdah


This is kind-of weird (but then, you're probably used to that by now :-) but you could override the actual "MyObject" constructor with a local one:

function MyObject() {
  function MyObject(p) {
    for (var k in p) if (p.hasOwnProperty(k)) this[k] = p[k];
  }

  this.public = new MyObject({
    publicMethod: function() { /* whatever */ },
    publicProperty: "something"
  });
  return this.public;
}

Clearly you could factor out the code for most of that, so that you could have a function that, given a function to perform the initialization for a particular class, would set all that up for you. (Having to maintain a system like you're proposing without some library support to handle the details seems like a real chore, and long-term a very hard thing to keep working, and even harder to change.)

like image 37
Pointy Avatar answered Sep 22 '22 13:09

Pointy