如何更改Nodejs调试控制台视图中对象的字符串表示形式

24

如何在nodejs调试控制台中更改对象实例的字符串表示。是否有一种方法(类似于.NET中的toString())可以重写?

enter image description here

考虑以下代码:

class SomeObject{
    constructor(){
        this._varA = "some text";
        this._varB = 12345;
        this._varC = "some more text";
        this._varD = true;
        this._varE = 0.45;
    }

    toString(){
        return "custom textual rapresentation of my object";
    }
}

var array = [];

array.push(new SomeObject());
array.push(new SomeObject());
array.push(new SomeObject());

console.log(array);

这将产生以下结果: 在此输入图片描述 然而,在我所使用的其他环境和编程语言中,覆盖 toString() 方法会显示 toString() 的结果(在上面的示例中是 "custom textual representation of my object"),而不是由调试器创建的动态文本表示(在上面的示例代码中,这是: SomeObject {_varA: "some text", _varB: 12345, _varC: "some more text", …})- 当没有定义自定义替代时,我毫不怀疑它非常有用。
我也意识到 console.log(array.toString()); 或者甚至 console.log(array.map(t=>t.toString())); 会产生类似于我想要的东西,但这样做会阻止我使用调试导航来浏览对象图。
如果这不可能,其他人是否会从中受益? 如果有足够的兴趣,我可以考虑将其定义和实现为一个功能。

已在 GitHub 上添加了此问题 - https://github.com/Microsoft/vscode/issues/46829 - Leo
像这样的东西呢? array.forEach(t=>{console.log(t.toString() + ":",t)});。虽然不是理想的解决方案,但我们可以创建一个节点模块来处理这种情况。例如,创建一个可以检查参数并根据类型进行操作的模块 :) - GuyT
1
@GuyT - 感谢您的建议,但这并不是理想的。在我看来,调试控制台(如我帖子中第二张图片所示)应该显示:SomeObject { "自定义文本表示我的对象" }而不是SomeObject {_varA: "一些文本", _varB: 12345, _varC: "更多文本", …} - Leo
我明白你的意思,另一个不太理想的解决方案是 array.forEach( el => {console.groupCollapsed(el.toString()); console.log(el); console.groupEnd();});。附注:我确实理解你设想的解决方案.. ;) - GuyT
5个回答

12
当你使用console.log时,它内部调用util.js中的formatValue函数,并执行以下检查:
const maybeCustomInspect = value[customInspectSymbol] || value.inspect;

这意味着如果您的值有一个inspect方法,它将被调用,然后您可以返回相同的toString。因此,请将您的代码更改为:
class SomeObject{
    constructor(){
        this._varA = "some text";
        this._varB = 12345;
        this._varC = "some more text";
        this._varD = true;
        this._varE = 0.45;
    }

    inspect(depth, opts) {
        return this.toString();
    }

    toString(){
        return "custom textual rapresentation of my object";
    }
}

var array = [];

array.push(new SomeObject());
array.push(new SomeObject());
array.push(new SomeObject());

console.log(array);

使其打印
[ custom textual rapresentation of my object,
  custom textual rapresentation of my object,
  custom textual rapresentation of my object ]

Nodejs也有相关文档。

https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_custom_inspection_functions_on_objects

根据文档,我使用的inspect方法已被弃用,正确的方法如下:

const util = require('util');

class SomeObject{
    constructor(){
        this._varA = "some text";
        this._varB = 12345;
        this._varC = "some more text";
        this._varD = true;
        this._varE = 0.45;
    }

    [util.inspect.custom](depth, options) {
        return this.toString();
    }

    toString(){
        return "custom textual rapresentation of my object";
    }
}

var array = [];

array.push(new SomeObject());
array.push(new SomeObject());
array.push(new SomeObject());

console.log(array);

编辑:2018年3月28日

因此,我使用以下方法启动脚本:

$ node --inspect-brk=54223 test.js 
Debugger listening on ws://127.0.0.1:54223/81094440-716b-42a5-895e-4ea2008e0dff
For help see https://nodejs.org/en/docs/inspector

然后使用以下命令运行 socat 转发器

$ socat -v TCP-LISTEN:54222,fork TCP:127.0.0.1:54223

当您在调试器中调试变量array时,将在socat终端上获得以下输出

socat

调试器重构了信息以给您提供有意义的表示。
现在,v8调试api并不知道我们想要像console.log一样不同地表示它。现在,在V8代码中可能存在类似的东西,但是查看源代码后,我无法确定是否存在这样的东西。因此,您可能需要向了解V8调试器api知识的人确认是否存在此类内容。
如果没有,那么您需要在IDE级别构建一些内容,这并不是一件容易的事情。

我尝试了这个方法,但它并没有改变调试控制台显示对象的方式... - Leo
你的编辑有点让我感到困惑,不确定你是否只在寻找 Console.log,我现在正在检查调试程序部分。 - Tarun Lalwani
谢谢你的回答和编辑 - 我只对在 vscode / vscode 调试器中实现此功能感兴趣。抱歉我应该在问题正文中提及而不仅仅依赖标签... 不管怎样,你得到了我的一票 :) - Leo

4

最近,VS Code新增了一个选项,可以对调试器输出进行微调:只需将以下内容添加到启动配置文件中即可。

"customDescriptionGenerator": "function (def) { if (this.toString) { const _v = this.toString(); if (_v.indexOf(\"[object Object]\") < 0) return _v; } return def; }",

Viola:使用“toString”在监视窗口中查看您的实体,同时保留深入挖掘等功能。


0

我的建议是: 如何重写console.log函数以实现你想要的功能。 以下是需要在任何对象中添加_toString函数来更改其在日志中出现方式的POC。

创建一个名为logger.js的文件,内容如下:

const getUpdatedLogObj = function(x){


    if(x && typeof x == 'object'){
            if(typeof x._toString === 'function'){
                return x._toString()
            } else {
                for(let i in x){
                    x[i] = getUpdatedLogObj(x[i])
                }
            }
        }
        return x;
    }



    console._log = console.log
    console.log = function(x){console._log(getUpdatedLogObj({...x}))}

在index.js中导入它

require('./logger')

console.log({a: 1, b: 2, c: {d: 5, e: 6, _toString: function(){return 'fromToString'}}})

而且你仍然可以获得导航: 在此输入图片描述


我也意识到console.log(array.toString());甚至console.log(array.map(t=>t.toString()));会产生类似于我想要的东西,但这将阻止我使用调试导航浏览对象,即深入到对象图中。 - Leo
名称_toString可能会误导,但您仍然可以通过上述实现获得导航: 已使用快照更新答案。 - thunder
谢谢您的回答,但这并没有为我的问题提供一个合适的解决方案。 - Leo

-1
const util = require('util');
class SomeObject{
constructor(){
    this._varA = "some text";
    this._varB = 12345;
    this._varC = "some more text";
    this._varD = true;
    this._varE = 0.45;
}

[util.inspect.custom](depth, options) {
    return this.toString();
}

toString(){
    return "custom textual rapresentation of my object";
}
}

var array = [];

array.push(new SomeObject());
array.push(new SomeObject());
array.push(new SomeObject());

console.log(array);

这怎么有助于任何事情呢? - Leo

-2

有一个toString()方法,你可以在另一个字符串上调用它。

terms[200]._text.toString()

您可能还在寻找JSON.stringify(),我发现它在调试中非常有用。由于JavaScript对象实际上就是JSON,因此这将使将它们打印到控制台变得更加简单。

console.log(JSON.stringify(terms[200]))


1
如果您要给我点踩,请留下原因,这样我就可以改进我的回答。 - Alec O
我不确定,但我认为可能是因为你的回答不是我的问题的有效答案...这可能部分是我的错,我会更新问题以使其更清晰...抱歉。 - Leo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接