简体   繁体   English

在 JavaScript ES6 中,如果 console.log() 不调用 obj.toString(),它使用什么?

[英]In JavaScript ES6, if console.log() doesn't invoke obj.toString(), what does it use?

Some related info is in this question: Within the standard JavaScript ES6 environment, when is .toString() ever called?这个问题中有一些相关信息: 在标准的 JavaScript ES6 环境中,什么时候调用 .toString()?

By polymorphism, toString() is the standard message to send to the object (or the standard method to invoke on the object), by the interface of the Object class.通过多态, toString()是通过 Object 类的接口发送给对象的标准消息(或在对象上调用的标准方法)。

But obviously, console.log() doesn't use it:但显然, console.log()不使用它:

// Inside of Node

> let aSet = new Set([1,3,5]);

> aSet.toString()
'[object Set]'

> console.log(aSet);
Set { 1, 3, 5 }

> let aMap = new Map([["foo", 1], ["bar", 2]])

> aMap.toString()
'[object Map]'

> console.log(aMap)
Map { 'foo' => 1, 'bar' => 2 }

so what does console.log() use?那么console.log()使用什么? It is not valueOf() , as valueOf() just returns the object itself in this case, when no primitive value is available.它不是valueOf() ,因为valueOf()在这种情况下只返回对象本身,当没有原始值可用时。

It'd be quite ugly to "special case" what class it is, and perform different actions -- as polymorphism, having the standard "verb", in this case toString() , is what is supposed to be used. “特殊情况”它是什么类并执行不同的操作会很丑陋 - 因为多态性,具有标准的“动词”,在这种情况下toString() ,是应该使用的。 To find out what the class is and perform different actions (such as using a switch statement), is exactly what we don't want to do in OOP.找出类是什么并执行不同的操作(例如使用 switch 语句),这正是我们在 OOP 中不想做的。

console.log() , along with other console methods, is implementation-dependent. console.log()以及其他console方法是依赖于实现的。

My answer applies only to Node.js.我的回答仅适用于 Node.js。


After some looking into the internal source files of Node.js, it turned out that in Node (v12), console methods use a common way to display values: the util.formatWithOptions method.在查看了 Node.js 的内部源文件后,发现在 Node (v12) 中, console方法使用一种常见的方式来显示值: util.formatWithOptions方法。

Its internal source is written in JavaScript, and it calls internal formatter functions (located in internal/util/inspect.js ), that formats objects based on their type, for example:它的内部源代码是用 JavaScript 编写的,它调用内部格式化程序函数(位于internal/util/inspect.js ),根据对象的类型格式化对象,例如:

  • Primitives are simply stringified.原语被简单地字符串化。
  • Plain objects are iterated over their properties, to show them.对普通对象的属性进行迭代,以显示它们。
  • Arrays are iterated over based on their length .数组根据它们的length进行迭代。
  • Set and Map objects' values are looked up using their iterators. SetMap对象的值使用它们的迭代器来查找。

The console is a host-provided object, and its implementation varies from host to host. console是主机提供的对象,其实现因主机而异。 Chrome's is different from Firefox's which is different from Node.js's which is different from... :-) Chrome 的与 Firefox 的不同,后者与 Node.js 的不同,后者不同于... :-)

Typically, they check the type of what you're logging and then show whatever the implementer thought was a reasonable representation of what you logged.通常,他们检查您记录的内容的类型,然后显示实施者认为是您记录的内容的合理表示的任何内容。 For objects and arrays, that usually involves querying the object/array for its contents (rather than calling toString ) and showing a representation of those contents.对于对象和数组,这通常涉及查询对象/数组的内容(而不是调用toString )并显示这些内容的表示。 (They may even query the contents using an internal feature of the JavaScript engine rather than going through the object's JavaScript-accessible API.) In "live" consoles like the ones in most browsers, the console even keeps a reference to the object so you can expand it and dive into its properties (details in the answers to this question ). (他们甚至可能使用 JavaScript 引擎的内部功能查询内容,而不是通过对象的 JavaScript 可访问 API。)在像大多数浏览器中的“实时”控制台中,控制台甚至保留对对象的引用,因此您可以扩展它并深入了解它的属性( 此问题的答案中有详细信息)。

(At one stage, Node.js's console looked for a method on the object called inspect and used that, but that turned out to be problematic for objects where inspect wasn't meant to be used that way and was removed. As far as I know they haven't added that back using a Symbol-named method instead.) (在一个阶段,Node.js的控制台看上去名为对象上的方法inspect和使用的,但原来是为那里的对象有问题的inspect是不是意味着要使用这种方式,并已被删除。至于我知道他们没有使用以符号命名的方法将其添加回来。)

There is a separate specification for console , provided by WHATWG community: Console Living Standard . WHATWG 社区提供了一个单独的console规范: Console Living Standard

When looking for console.log in that specification you get via the section 2.1 Logger to the section 2.3 Printer , which states:在该规范中查找console.log时,您可以通过部分2.1 Logger获得部分2.3 Printer ,其中指出:

How the implementation prints args is up to the implementation, but implementations should separate the objects by a space or something similar, as that has become a developer expectation.实现如何打印args取决于实现,但实现应该用空格或类似的东西分隔对象,因为这已成为开发人员的期望。

Typically, a console implementation will want to give a rich user interface, with expandable items, styling, allowing to drill down to the primitive values that build up the overall value.通常,控制台实现将希望提供丰富的用户界面,具有可扩展的项目、样式,允许深入到构建整体值的原始值。 It does not have to be implemented in JavaScript, and calling toString may not be that handy any way, knowing that even ({ a: 1 }).toString() returns "[object Object]" , which is not that useful.它不必在 JavaScript 中实现,并且调用toString可能不是那么方便,知道即使({ a: 1 }).toString()返回"[object Object]" ,这也不是那么有用。

Sometimes the given information goes beyond to what you could query synchronously in code, as is the case with promise objects.有时,给定的信息超出了您可以在代码中同步查询的内容,就像 promise 对象的情况一样。 In the console the current state of such objects is output, while in code you need to at least call then (or do an await ) to get that info.在控制台中,输出这些对象的当前状态,而在代码中,您至少需要调用then (或执行await )以获取该信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM