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

Posted

技术标签:

【中文标题】如何在 Nodejs 调试控制台视图中更改对象的字符串表示【英文标题】:How to change string representation of objects in Nodejs debug console view 【发布时间】:2018-08-28 04:08:09 【问题描述】:

如何在 nodejs 调试控制台中更改对象实例的字符串表示。有没有可以覆盖的方法(如 .NET 中的 toString())?

考虑以下代码:

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 - github.com/Microsoft/vscode/issues/46829 还有这样的事情? array.forEach(t=>console.log(t.toString() + ":",t));。这并不理想,但我们可以创建一个节点模块来处理这种情况。例如,创建一个检查参数并作用于类型的模块:) @GuyT - 感谢您的建议,但这并不理想。在我看来,调试控制台(如我帖子中的第二张图片所示)应该显示:SomeObject "custom textual rapresentation of my object" 而不是 SomeObject _varA: "some text", _varB: 12345, _varC: "some more text", … 我明白你的意思,另一个不理想的解决方案是array.forEach( el => console.groupCollapsed(el.toString()); console.log(el); console.groupEnd(););。附言。我确实了解您设想的解决方案是什么.. ;) 【参考方案1】:

有一个 toString() 方法可以调用另一个字符串。

terms[200]._text.toString()

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

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

【讨论】:

如果您要投反对票,请留下理由,以便我改进答案。 我不确定,但我认为这可能是因为您的回答不是我问题的有效答案......这也可能部分是我的坏事,我会更新问题以更清楚。 ..对不起。【参考方案2】:

当您执行console.log 时,它会在内部调用formatValue 中的util.js,它有以下检查

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 终端上得到以下输出

这些信息是由调试器重构的,为您提供有意义的表示。

现在v8 调试 api 不知道我们想要以不同的方式表示它,就像我们为 console.log 所做的那样。现在V8 代码中可能有类似的东西做类似的事情,但是查看源代码,我无法弄清楚是否存在这样的事情。所以你可能需要从有 V8 调试器 api 知识的人那里确认,如果存在这种东西

如果不是,您需要在 IDE 级别构建一些东西,这又不是一件容易的事

【讨论】:

我试过了,它对调试控制台显示对象的方式没有任何影响... 你的编辑让我很困惑,你只是在寻找Console.log,我现在正在检查调试器部分 感谢您的回答和编辑 - 我只对在 vscode / vscode 调试器中工作感兴趣。抱歉,我应该在我的问题正文中提到这一点,而不仅仅是依赖标签......无论如何,你有我的 +1 :) 这是最接近我的问题的答案。这不是我的问题的解决方案,但它很清楚且很有帮助,因此我将赏金奖励给了它。谢谢@TarunLalwani【参考方案3】:

我的两分钱: 如何覆盖 console.log 函数来做你想做的事。 这是 POC,它需要任何对象中的 _toString 函数来更改它在日志中的显示方式。

创建一个包含以下内容的文件 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()));会产生类似于我所追求的东西,但是这会阻止我使用调试导航来导航对象,即。深入到对象图中。 名称 _toString 可能会产生误导,但您仍然可以通过上述实现获得导航:使用快照更新答案 感谢您的回答,但这并没有为我的问题提供合适的解决方案。【参考方案4】:
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);

【讨论】:

这有什么帮助?【参考方案5】:

VS Code 中添加了一个新选项,可以调整调试器输出:只需将以下内容添加到您的启动配置中

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

Viola:在手表中使用“toString”查看您的实体,保留向下钻取等功能。

【讨论】:

以上是关于如何在 Nodejs 调试控制台视图中更改对象的字符串表示的主要内容,如果未能解决你的问题,请参考以下文章

如何继承 ASP.NET MVC 控制器并仅更改视图?

ios 8 更改呈现/模态视图控制器的大小

如何使用DevTools调试Nodejs运行的Javascript

重新排序单元格后如何更改获取结果控制器数组中对象的顺序

从一个视图控制器更改项目中所有视图的背景颜色?

NodeJs VSCode 断点调试