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开发者_Go百科._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.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.
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.
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.)
精彩评论