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

dev*_*os1 107 javascript debugging tostring

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

在C#中,我习惯于重写ToString()以能够自定义对象的调试器表示.我能在JavaScript中做些什么吗?

Mic*_*tor 98

您也可以toString在Javascript中覆盖.见例子:

function Foo() 
{
}

// toString override added to prototype of Foo class
Foo.prototype.toString = function()
{
    return "[object Foo]";
}

var f = new Foo();
alert(f);  // popup displays [object Foo]
Run Code Online (Sandbox Code Playgroud)

对如何在JavaScript中确定对象类型名称的讨论.

  • 'Object.prototype.toString.call(f)仍将显示[object Object].是的,因为这是一个完全不同于'Foo.prototype.toString'的函数,哈哈. (14认同)
  • 虽然确实警报函数将显示覆盖原型`toString`属性的函数的返回值,`Object.prototype.toString.call(f)`仍将显示`[object Object]`. (8认同)
  • 如果像我这样的人最后出现在这里,则可以在ES6中使用Sybmol.toStringTag来自定义Object.prototype.toString.call行为。https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toStringTag (2认同)

Max*_*ber 27

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

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

var foo = new Foo();
Run Code Online (Sandbox Code Playgroud)

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

//using JS implicit type conversion
console.log('' + foo);
Run Code Online (Sandbox Code Playgroud)

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

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

用法:

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

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

更新

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'
Run Code Online (Sandbox Code Playgroud)

  • console.log(''+ foo); 这是问题我没有看到任何toString实现,直到我达到你的答案. (5认同)

Pau*_*l V 13

在浏览器JS中获取可调试输出的简单方法是将对象序列化为JSON.所以你可以打个电话

console.log ("Blah: " + JSON.stringify(object));
Run Code Online (Sandbox Code Playgroud)

因此,举例来说,alert("Blah! " + JSON.stringify({key: "value"}));使用文本生成警报Blah! {"key":"value"}


小智 8

使用模板文字

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

const foo = new Foo();
console.log(`${foo}`); // 'I am foo'
Run Code Online (Sandbox Code Playgroud)


Sys*_*ank 7

如果您使用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 );
Run Code Online (Sandbox Code Playgroud)

这将产生:

{ #Point 1,2 }
Run Code Online (Sandbox Code Playgroud)

没有检查的版本打印:

{ x: 1, y: 2 }
Run Code Online (Sandbox Code Playgroud)


Dan*_*eld 7

“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]
Run Code Online (Sandbox Code Playgroud)

class Person {
  constructor(name) {
    this.name = name
  }
  get [Symbol.toStringTag]() {
    return 'Person';
  }
}

let p = new Person('Dan');
Object.prototype.toString.call(p); // [object Person]
Run Code Online (Sandbox Code Playgroud)

某些 Javascript 类型(例如 Maps 和 Promises)toStringTag定义了内置符号

Object.prototype.toString.call(new Map());       // "[object Map]"
Object.prototype.toString.call(Promise.resolve()); // "[object Promise]"
Run Code Online (Sandbox Code Playgroud)

因为Symbol.toStringTag是一个众所周知的符号,我们可以引用它并验证上述类型确实具有 Symbol.toStringTag 属性 -

new Map()[Symbol.toStringTag] // 'Map'
Promise.resolve()[Symbol.toStringTag] // 'Promise'
Run Code Online (Sandbox Code Playgroud)


Mat*_*all 6

只需覆盖该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
Run Code Online (Sandbox Code Playgroud)

定义新类型时,它会更好:

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}"
Run Code Online (Sandbox Code Playgroud)

  • 此代码无法解决OP的console.log问题,至少不在node.js`v0.10.*`或Chrome`版本32.0.1700.102`中.虽然直接调用toString(lame)或使用类型强制(lamer)将使用它,控制台[/ info | log /]使用旧的pre-mod toString. (9认同)

小智 5

如果对象是由您自己定义的,则始终可以添加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);
Run Code Online (Sandbox Code Playgroud)