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?

Share Improve this question edited Aug 31, 2012 at 14:52 Rap 7,2823 gold badges52 silver badges93 bronze badges asked Jun 10, 2011 at 14:08 devios1devios1 37.9k48 gold badges167 silver badges266 bronze badges 2
  • 2 I find that output is the most reliable way of telling you what a variable holds (or at least better than typeof). – alex Commented Jun 10, 2011 at 14:11
  • 1 Be aware that toString() is only used during coercion. console.log(obj); won't call your custom toString(); console.log(`${obj}`); and console.log(obj + ""); will. – Daniel Kaplan Commented Jul 14, 2024 at 6:37
Add a comment  | 

16 Answers 16

Reset to default 122

You 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 classes):

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;
};

本文标签: