是否有可能覆盖 JavaScript 的 toString()函数来为调试提供有意义的输出?

当我在 JavaScript 程序中使用 console.log()对象时,我只看到输出 [object Object],这对于确定它是什么对象(甚至是什么类型的对象)没有多大帮助。

在 C # 中,我习惯于重写 ToString(),以便能够自定义对象的调试器表示形式。在 JavaScript 中有什么类似的操作吗?

120577 次浏览

你也可以在 Javascript 中覆盖 toString:

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]

请参阅关于如何在 JavaScript 中确定对象类型名称的 这个讨论。

Chrome 控制台日志允许你检查对象。

只需覆盖 toString()方法。

举个简单的例子:

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

当您定义一个新类型时,它会做得更好:

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

您可以为任何自定义对象提供它们自己的 toString 方法,或者编写一个通用的方法,您可以对正在查看的对象调用-

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

如果包含 JavaScript 库原型,可以使用 Object.inspect()获得更有用的表示,而不是重写 toString()

大多数流行的框架都包含类似的内容。

在浏览器 JS 中获得可调试输出的一种简单方法是将对象序列化为 JSON。这样你就可以打个电话

console.log ("Blah: " + JSON.stringify(object));

例如,alert("Blah! " + JSON.stringify({key: "value"}));生成一个带有文本 Blah! {"key":"value"}的警报

如果对象是由您自己定义的,那么您总是可以添加 toString 覆盖。

//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);

首先覆盖对象或原型的 toString:

var Foo = function(){};
Foo.prototype.toString = function(){return 'Pity the Foo';};


var foo = new Foo();

然后转换为字符串以查看对象的字符串表示形式:

//using JS implicit type conversion
console.log('' + foo);

如果不喜欢额外的输入,可以创建一个函数,将其参数的字符串表示形式记录到控制台:

var puts = function(){
var strings = Array.prototype.map.call(arguments, function(obj){
return '' + obj;
});
console.log.apply(console, strings);
};

用法:

puts(foo)  //logs 'Pity the Foo'


puts(foo, [1,2,3], {a: 2}) //logs 'Pity the Foo 1,2,3 [object Object]'

更新

E2015为这些东西提供了更好的语法,但是您必须使用像 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'
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;
};

如果您正在使用 Node,那么可能值得考虑 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 );

这将产生:

{ #Point 1,2 }

而未经检查的版本打印:

{ x: 1, y: 2 }

更多资料(+ classes 中使用的示例) :

Https://nodejs.org/api/util.html#util_util_inspect_custom

模板文字:

class Foo {
toString() {
return 'I am foo';
}
}


const foo = new Foo();
console.log(`${foo}`); // 'I am foo'

您可以在 JS 中扩展或重写

String.prototype.toString = function() {
return this + "..."
}
document.write("Sergio".toString());

这次行动需要很多时间 根据 Mozilla 的文档,它的使用是不被鼓励的: Https://developer.mozilla.org/es/docs/web/javascript/referencia/objetos_globales/object/proto

- 显然,现代浏览器已经过时了。原型和 ECMA6指定 使用正确的 _ _ proto _ _ 代替。

例如,如果您定义自己的对象 地理位置,那么应该调用 < em > _ _ proto _ _ 属性而不是 。原型:

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());

下面是一个如何将 Map 对象字符串化的示例:

  Map.prototype.toString = function() {


let result = {};


this.forEach((key, value) => { result[key] = value;});


return JSON.stringify(result);
};

‘ Symbol.toStringTag’属性添加到自定义对象或类。

分配给它的字符串值将是它的默认字符串描述,因为它是由 Object.prototype.toString()方法在内部访问的。

例如:

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

一些 Javascript 类型,比如 Maps 和 Promises,定义了一个内置的 toStringTag符号

Object.prototype.toString.call(new Map());       // "[object Map]"
Object.prototype.toString.call(Promise.resolve()); // "[object Promise]"

因为 Symbol.toStringTag众所周知的标志,所以我们可以引用它并验证上述类型是否具有 Symbol.toStringTag 属性-

new Map()[Symbol.toStringTag] // 'Map'
Promise.resolve()[Symbol.toStringTag] // 'Promise'