请教一个JS类型推导的问题?

作者站长头像
站长
· 阅读数 6

问题来自力扣第129题:https://leetcode.cn/problems/sum-root-to-leaf-numbers/

但问题并不是要解题,题目我自己提交成功提交了。

我的问题是

下面示例中提供的root参数提示是TreeNode类型,如何复现这个TreeNode类型

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var sumNumbers = function(root) {
};

演示案例

以下采用示129题中的例1进行演示,提示:root并非数组

root = [1,2,3]

我的尝试

我先将root打印了一遍,如下:

var sumNumbers = function(root) {
    console.log('root', root, root.left, root.length);
};

结果如下:

root, [1,2,3], [2], undefined

可以得到以下结论:

  • root参数不是数组,因为它没有数组相关的属性
  • 但在console打印中,root展示为数组格式

我先试着这样赋值数组,打印结果不对:

const root = [];
root.val = 1;
root.left = 2;
root.right = 3;

console.log(root);
// error, output: [val: 1, left: 2, right: 3]

然后我试着直接按照注释将对象还原,打印结果还是不对:

function TreeNode(val, left, right) {
    this.val = (val===undefined ? 0 : val)
    this.left = (left===undefined ? null : left)
    this.right = (right===undefined ? null : right)
}

l1 = new TreeNode(4)
r1 = new TreeNode(5)
a = new TreeNode(1, l1, r1);

console.log(a);
// error, output: TreeNode {val: 1, left: TreeNode, right: TreeNode}

然后尝试把root解构:

console.log('object like array:', root);
var s = "";
for (var property in root) {
   s = s + "\n "+property +": " + root[property] ;
}

console.log(s);

输入如下:

object like array: [1,2,3]

 val: 1
 left: [object Object]
 right: [object Object]

问题

请问如何做到将一个对象包装成数组类型?

回复
1个回答
avatar
test
2024-06-26
  1. 获取节点的构造函数:

    console.log(Object.getPrototypeOf(node).constructor.toString());

    内容为:

    function TreeNode(val, left, right) {
     this.val = (val===undefined ? 0 : val);
     this.left = (left===undefined ? null : left)
     this.right = (right===undefined ? null : right)
    }
    和你复现的写法完全一致。
  2. 获取上述构造函数的原型对象:

    console.log(Object.getPrototypeOf(node).constructor).prototype

    从这里得知该原型为:

    {
      [Symbol(nodejs.util.inspect.custom)]: [Function (anonymous)]
    }
    上面只有一个方法Symbol(nodejs.util.inspect.custom)
  3. 打印上面的方法:

    console.log(
      Object.getPrototypeOf(node).constructor
    .prototype[Symbol.for('nodejs.util.inspect.custom')].toString()
    )

    得到该方法的源代码:

    function (depth, opts) {
      return serializer.serializeTree(this);
    }

    serializer 不在全局环境,应该在模块或者定义TreeNode的封闭作用域(闭包)中,无法检测其函数源代码,不过从这个名字来看,是一个序列化函数。根据掘金文章util inspect node

    util.inspect是Node.js中的一个模块,它提供了将任何JavaScript对象转换为字符串的功能。它通常用于调试和日志记录。当您在Node.js中使用util.inspect函数时,它会返回一个表示传递对象的字符串。您可以通过传递不同的选项来自定义字符串的格式。例如,您可以指定缩进、深度、颜色等选项。
  4. 从上述描述看,这个函数的作用是在打印的时候把对象序列化为指定的字符串。
  5. 如果要验证上述猜想,可以:

    const key = Symbol.for("nodejs.util.inspect.custom");
    class SubTreeNode extends TreeNode{
     [key](){
         return "Exactly!"
     }
    }
    console.log(new SubTreeNode(8)); // Exactly!

不过浏览器开发者工具的console.log与 Node JS 环境下的行为并不一致,浏览器开发者工具中打印的时候,并不会将对象序列化为字符串,所以在浏览器中较难模拟这样的行为(可以通过toString方法自定义序列化方案,但只在拼接字符串的时候有效)。至于将树展开成为数组的具体方案,应该是做了一个广度优先遍历。

回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容