admin管理员组文章数量:1134249
When I console.log()
an object in my JavaScript program, I just see the output [object Object]
, which is not very helpful in figuring out what object (or even what type of object) it is.
In C# I'm used to overriding ToString()
to be able to customize the debugger representation of an object. Is there anything similar I can do in JavaScript?
When I console.log()
an object in my JavaScript program, I just see the output [object Object]
, which is not very helpful in figuring out what object (or even what type of object) it is.
In C# I'm used to overriding ToString()
to be able to customize the debugger representation of an object. Is there anything similar I can do in JavaScript?
16 Answers
Reset to default 122You can override toString
in Javascript as well. See example:
function Foo() {}
// toString override added to prototype of Foo class
Foo.prototype.toString = function() {
return "[object Foo]";
}
var f = new Foo();
console.log("" + f); // console displays [object Foo]
See this discussion on how to determine object type name in JavaScript.
First override toString
for your object or the prototype:
var Foo = function(){};
Foo.prototype.toString = function(){return 'Pity the Foo';};
var foo = new Foo();
Then convert to string to see the string representation of the object:
//using JS implicit type conversion
console.log('' + foo);
If you don't like the extra typing, you can create a function that logs string representations of its arguments to the console:
var puts = function(){
var strings = Array.prototype.map.call(arguments, function(obj){
return '' + obj;
});
console.log.apply(console, strings);
};
Usage:
puts(foo) //logs 'Pity the Foo'
puts(foo, [1,2,3], {a: 2}) //logs 'Pity the Foo 1,2,3 [object Object]'
Update
E2015 provides much nicer syntax for this stuff, but you'll have to use a transpiler like Babel:
// override `toString`
class Foo {
toString(){
return 'Pity the Foo';
}
}
const foo = new Foo();
// utility function for printing objects using their `toString` methods
const puts = (...any) => console.log(...any.map(String));
puts(foo); // logs 'Pity the Foo'
Add the 'Symbol.toStringTag' property to the custom object or class.
The string value which is assigned to it will be its default string description because it is accessed internally by the Object.prototype.toString()
method.
For example:
class Person {
constructor(name) {
this.name = name
}
get [Symbol.toStringTag]() {
return 'Person';
}
}
let p = new Person('Dan');
Object.prototype.toString.call(p); // [object Person]
class Person {
constructor(name) {
this.name = name
}
get[Symbol.toStringTag]() {
return 'Person';
}
}
let p = new Person('Dan');
console.log(Object.prototype.toString.call(p));
Some Javascript types such as Maps and Promises have a built-in toStringTag
symbol defined
Object.prototype.toString.call(new Map()); // "[object Map]"
Object.prototype.toString.call(Promise.resolve()); // "[object Promise]"
Because Symbol.toStringTag
is a well-known symbol, we can reference it and verify that the above types do have the Symbol.toStringTag property -
new Map()[Symbol.toStringTag] // 'Map'
Promise.resolve()[Symbol.toStringTag] // 'Promise'
If you are using Node it might be worth considering util.inspect
.
var util = require('util')
const Point = {
x: 1,
y: 2,
[util.inspect.custom]: function(depth) { return `{ #Point ${this.x},${this.y} }` }
}
console.log( Point );
This will yield:
{ #Point 1,2 }
While the version without inspect prints:
{ x: 1, y: 2 }
More information (+ an example for using in class
es):
https://nodejs.org/api/util.html#util_util_inspect_custom
An easy way to get debuggable output in browser JS is to just serialize the object to JSON. So you could make a call like
console.log ("Blah: " + JSON.stringify(object));
So for an example, alert("Blah! " + JSON.stringify({key: "value"}));
produces an alert with the text Blah! {"key":"value"}
With template literals:
class Foo {
toString() {
return 'I am foo';
}
}
const foo = new Foo();
console.log(`${foo}`); // 'I am foo'
If the object is defined by yourself you can always add a toString override.
//Defined car Object
var car = {
type: "Fiat",
model: 500,
color: "white",
//.toString() Override
toString: function() {
return this.type;
}
};
//Various ways to test .toString() Override
console.log(car.toString());
console.log(car);
alert(car.toString());
alert(car);
//Defined carPlus Object
var carPlus = {
type: "Fiat",
model: 500,
color: "white",
//.toString() Override
toString: function() {
return 'type: ' + this.type + ', model: ' + this.model + ', color: ' + this.color;
}
};
//Various ways to test .toString() Override
console.log(carPlus.toString());
console.log(carPlus);
alert(carPlus.toString());
alert(carPlus);
Just override the toString()
method.
Simple example:
var x = {foo: 1, bar: true, baz: 'quux'};
x.toString(); // returns "[object Object]"
x.toString = function () {
var s = [];
for (var k in this) {
if (this.hasOwnProperty(k)) s.push(k + ':' + this[k]);
}
return '{' + s.join() + '}';
};
x.toString(); // returns something more useful
It does even better when you define a new type:
function X()
{
this.foo = 1;
this.bar = true;
this.baz = 'quux';
}
X.prototype.toString = /* same function as before */
new X().toString(); // returns "{foo:1,bar:true,baz:quux}"
You can give any custom objects their own toString methods, or write a general one that you can call on the object you are looking at-
Function.prototype.named= function(ns){
var Rx= /function\s+([^(\s]+)\s*\(/, tem= this.toString().match(Rx) || "";
if(tem) return tem[1];
return 'unnamed constructor'
}
function whatsit(what){
if(what===undefined)return 'undefined';
if(what=== null) return 'null object';
if(what== window) return 'Window object';
if(what.nodeName){
return 'html '+what.nodeName;
}
try{
if(typeof what== 'object'){
return what.constructor.named();
}
}
catch(er){
return 'Error reading Object constructor';
}
var w=typeof what;
return w.charAt(0).toUpperCase()+w.substring(1);
}
-This operation takes lot of time to complete, and it's use is discouraged according to mozilla docs: https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Object/proto
-Apparently, modern browsers deprecated .prototype and ECMA6 specifies using proper__proto__ instead.
So for example, if you are defining you own object geoposition you should call __proto__ property instead of .prototype:
var geoposition = {
lat: window.pos.lat,
lng: window.pos.lng
};
geoposition.__proto__.toString = function(){ return "lat: "+this.lat+", lng: "+this.lng }
console.log("Searching nearby donations to: "+geoposition.toString());
Here's an example how to stringify a Map object:
Map.prototype.toString = function() {
let result = {};
this.forEach((key, value) => { result[key] = value;});
return JSON.stringify(result);
};
To update all objects toString()
method you can use object prototype:
Object.prototype.toString = function () {
console.log("TO STRING WORKS FOR: ", this);
return JSON.stringify(this);
};
Rather than overriding toString()
, if you include the Prototype JavaScript Library, you can use Object.inspect()
to get a much more useful representation.
Most popular frameworks include something similar.
You can't!
In 2023 Chrome doesn't base it's console output on anything you can control.
The best you can do, is output it to console.log lines which force object coercion.
The Chrome console log allows you to inspect the object.
A simple format Date function using Javascript prototype, it can be used for your purpose
https://gist.github.com/cstipkovic/3983879 :
Date.prototype.formatDate = function (format) {
var date = this,
day = date.getDate(),
month = date.getMonth() + 1,
year = date.getFullYear(),
hours = date.getHours(),
minutes = date.getMinutes(),
seconds = date.getSeconds();
if (!format) {
format = "MM/dd/yyyy";
}
format = format.replace("MM", month.toString().replace(/^(\d)$/, '0$1'));
if (format.indexOf("yyyy") > -1) {
format = format.replace("yyyy", year.toString());
} else if (format.indexOf("yy") > -1) {
format = format.replace("yy", year.toString().substr(2, 2));
}
format = format.replace("dd", day.toString().replace(/^(\d)$/, '0$1'));
if (format.indexOf("t") > -1) {
if (hours > 11) {
format = format.replace("t", "pm");
} else {
format = format.replace("t", "am");
}
}
if (format.indexOf("HH") > -1) {
format = format.replace("HH", hours.toString().replace(/^(\d)$/, '0$1'));
}
if (format.indexOf("hh") > -1) {
if (hours > 12) {
hours -= 12;
}
if (hours === 0) {
hours = 12;
}
format = format.replace("hh", hours.toString().replace(/^(\d)$/, '0$1'));
}
if (format.indexOf("mm") > -1) {
format = format.replace("mm", minutes.toString().replace(/^(\d)$/, '0$1'));
}
if (format.indexOf("ss") > -1) {
format = format.replace("ss", seconds.toString().replace(/^(\d)$/, '0$1'));
}
return format;
};
本文标签:
版权声明:本文标题:Is it possible to override JavaScript's toString() function to provide meaningful output for debugging? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736756112a1951297.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
typeof
). – alex Commented Jun 10, 2011 at 14:11toString()
is only used during coercion.console.log(obj);
won't call your customtoString()
;console.log(`${obj}`);
andconsole.log(obj + "");
will. – Daniel Kaplan Commented Jul 14, 2024 at 6:37