Let's say I have this class.
class Attribute {
constructor(name) {
this.name = name;
}
}
And I create an instance and log it to the console for debugging purposes.
const test = new Attribute('Large');
console.log(test);
How can I get it to output a specially formatted string, like {Attribute} Large
? I'm primarily concerned with Chrome support, but Node and other browsers would be nice, too.
Let's say I have this class.
class Attribute {
constructor(name) {
this.name = name;
}
}
And I create an instance and log it to the console for debugging purposes.
const test = new Attribute('Large');
console.log(test);
How can I get it to output a specially formatted string, like {Attribute} Large
? I'm primarily concerned with Chrome support, but Node and other browsers would be nice, too.
- 1 override Attribute.prototype.toString – Jonas Wilms Commented Apr 14, 2017 at 17:42
-
3
@Jonasw Doesn't really work unless you do
console.log(test.toString())
. – Derek 朕會功夫 Commented Apr 14, 2017 at 17:43 -
1
Probably use a custom logging function. For NodeJS, I would remend using
util.format
to format theprocess.stdout
to create a custom logger. You can overrideconsole.log
too, but it is not a good way to deal with stuff. – Ozil Commented Apr 14, 2017 at 17:50 - Does this answer your question? Is it possible to override JavaScript's toString() function to provide meaningful output for debugging? – ggorlen Commented Feb 4, 2022 at 1:47
3 Answers
Reset to default 8A sane solution would probably be to use a custom logging function that stringifies Attribute
values.
However, if you have a vendetta against people who need to maintain your code in the future, one solution that meets the technical requirements of this question is to have your class extend a type that console.log
automatically serializes to string, like RegExp
. When you console.log
a RegExp
instance, Chrome (and probably other environments) automatically serializes it to its bare /.../
expression. Simply overwrite what string it should serialize to by supplying a custom toString
function, and you've got exactly what you asked for.
class Attribute extends RegExp {
constructor(name) {
super();
this.name = name;
}
toString() {
return this.name
}
}
var test = new Attribute('Large');
console.log(test);
This is roughly equivalent to answering the question "How do I stop my house from flooding?" with "Put your house on a giant raft" instead of "Put some caulk in your basement" or "Move somewhere else." Some side effects will include:
Your objects will inherit regular expression properties like
global
andexec
Testing if your object is
instanceof RegExp
will of course return true, which might cause your object to be valid inputs for routines that only expect to operate on regular expression objects
Using further dark magic, you can solve the these issues by doing
Object.setPrototypeOf(Attribute.prototype, Object.prototype);
immediately after your class
definition, which will ensure that your this
object will simply be run through the RexExp
constructor (thereby flagging it for stringified log
output) but not inherit from RexExp.prototype
. By mixing class
and prototype
syntax together, you also ensure that your code is confusing and everyone is actively afraid of it.
apsiller's answer works great in Chrome and Firefox, but unfortunately, it doesn't work in Node. However, after some experimentation and research, I found a solution that does work in Node.
It turns out that Node's implementation of console.log
has a built-in customization point, util.inspect.custom
, so all you have to do is define a method with that symbol that returns whatever you want to print.
class Attribute {
constructor(name) {
this.name = name;
}
[require('util').inspect.custom](){
return `{Attribute} ${this.name}`;
}
}
class Attribute {
constructor(name) {
this.name = name;
}
toString(){//simply set the to String method?
return "{Attribute} "+this.name;
}
}
As console.log does not call to String you either do:
const test = new Attribute('Large');
console.log(test+"");
or you create your own logging function