【问题标题】:Printing out javascript objects打印出 javascript 对象
【发布时间】:2021-04-30 04:44:04
【问题描述】:

在下面的示例中,我有两个 console.log,每次都得到不同的答案(尽管我希望得到相同的答案)。

class Dog {
  constructor(name, gender) {
    this.name = name;
    this.gender = gender;
  }
  toString() {
    return this.name;
  }
}

let maxi = new Dog('john', 'male');
console.log(maxi) // Dog { name: 'john', gender: 'male' }
console.log(`${maxi}`); // john

在第一个示例中,我似乎在记录对象的类型及其属性。然而,在第二个示例中,我的自定义 toString() 方法似乎被用于将对象转换为字符串。

为什么不一样?文档中是否有地方解释了为什么字符串文字使用 toString() 方法将对象转换为字符串,而 console.log() 没有。另外,console.log() 甚至在哪里拉取对象的这个字符串表示?

谢谢!

【问题讨论】:

  • console.log(maxi) 不记录对象的字符串表示形式。对象和原型链的表示取决于浏览器。但是,它记录对对象的引用。如果要更新对象,如果您在控制台中展开先前记录的对象,它将显示更新的属性。
  • toString 行为是预期的。每当对象被强制为字符串时,它就会调用对象上的toString 方法:MDN: Overriding the default toString method
  • @adiga 和 console.log() 不强制使用字符串? console.log 如何打印对对象的引用?
  • @bugsyb 在哪个环境下,node.js还是浏览器还是别的什么?正如阿迪加所说,在调试器中console.log 不会打印文本,而是显示对象的实时表示,您可以在事后检查。

标签: javascript javascript-objects tostring


【解决方案1】:

如果您在 chrome 或 firefox 的最新版本中记录对象,您所记录的是对该对象的引用,而在您调用 console.log() 时可能不是“值”。但它是当时对象的价值。 参考:Mozilla

那么如何解决这个问题,将你的对象转换成一个字符串(你的日志2),例如:

class Dog {
    constructor(name, gender) {
      this.name = name;
      this.gender = gender;
    }
    toString() {
      return this.name;
    }
  }
  
  let maxi = new Dog('john', 'male');
  console.log('Dog: ' + maxi) // Dog { name: 'john', gender: 'male' }
  console.log(`${maxi}`); // {"name":"john","gender":"male"}

这是可行的,因为我使用 + 运算符而不是 , 运算符,因此他会将其粘贴到字符串中,而不是引用您的对象。

总结 变量不存储对象的值,而是该值的引用(内存中的地址)。所以你复制那个引用而不是对象。

【讨论】:

    【解决方案2】:

    因为我认为您的要求是以字符串形式打印对象,所以我在下面有这个解决方案。

    哦,我在这里使用了箭头功能??。您可以使用普通的 es5 功能。 谢谢。

    class Dog {
      constructor(name, gender) {
        this.name = name;
        this.gender = gender;
      }
      toString() {
        return JSON.stringify(this);
      }
    }
    
    let maxi = new Dog('john', 'male');
    console.log(`${maxi}`); // {"name":"john","gender":"male"}
    

    【讨论】:

    • console.log(typeof(maxi)) 不会打印Dog { name: 'john', gender: 'male' }。而且绝对没有理由在这里使用箭头函数,因为这里的方法要好得多! (虽然不是 ES5 function
    • @Bergi 我同意没有理由使用箭头函数here,但请解释为什么使用实例方法声明比分配匿名箭头函数“好得多”一个类属性。后者实际上是避免在构造函数中执行 this.methodName = this.methodName.bind(this) 的推荐方法,例如对于用作事件侦听器的方法。
    • @Bergi ,哈哈哈我知道 typeof(maxi) 不会打印我刚刚用于理解目的的对象。但问题是下一行给出了解决方案。我们可以同时使用箭头 fn 和 Es5 fn。我习惯使用箭头函数,这就是我使用它的原因。使用它没有任何问题。
    • @connexo 首先,类字段仍然是实验性语法,没有什么是理所当然的。其次,它们效率较低,需要更多内存,当不用作事件侦听器时,这绝对是不必要的 toJSON。第三,它们不能与继承正常工作。有关更多信息,请参阅medium.com/@charpeni/…。它们不应该成为一种习惯。所以在这种情况下,这种改变是绝对没有根据的。
    • @Bergi 该帖子列出了类属性转译方式的问题,而不是功能本身的问题。不过,转译正在成为过去。此外,让我感到惊讶的是,有多少方法没有绑定到实例本身对于 React 开发人员来说似乎是一个巨大的障碍。
    【解决方案3】:

    我认为 Console.log 在内部使用 toJSON 方法将对象传输到字符串。所以必须自己写toJSON...

        class Dog {
          constructor(name, gender) {
            this.name = name;
            this.gender = gender;
          }
          toJSON() {
            return this.name;
          }
        }
        let maxi = new Dog('john', 'male');
        console.log(maxi) // Dog { name: 'john', gender: 'male' }
        console.log(`${maxi}`); // john
    

    这真的行不通……正如 Bergi 告诉我的那样,他是对的。我尝试了没有删除原始代码的代码: toString() { ... } 并像这样添加 toJSON() {...} 和 '>>>' :console.log('>>>'+maxi) 和输出//>>>约翰。所以,我认为 toJSON() 给出了 //>>>john,但它是 toString()。谢谢你,Bergi。

    【讨论】:

    • 不,它不使用toJSON
    • 我在node上运行代码,输出为:john john
    • 我无法复制。运行您的代码时,我得到Dog { name: 'john', gender: 'male' }[object Object]
    • 你是对的...我这样修改它:console.log('>>>'+maxi) 并输出//>>>john
    • 没有。即使这样也只适用于toString,不适用于toJSON
    猜你喜欢
    • 1970-01-01
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多