简体   繁体   中英

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?

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.

But obviously, console.log() doesn't use it:

// 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? It is not valueOf() , as valueOf() just returns the object itself in this case, when no primitive value is available.

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. 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.

console.log() , along with other console methods, is implementation-dependent.

My answer applies only to 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.

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:

  • Primitives are simply stringified.
  • Plain objects are iterated over their properties, to show them.
  • Arrays are iterated over based on their length .
  • Set and Map objects' values are looked up using their iterators.

The console is a host-provided object, and its implementation varies from host to host. Chrome's is different from Firefox's which is different from Node.js's which is different from... :-)

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. (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 ).

(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.)

There is a separate specification for console , provided by WHATWG community: 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:

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.

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.

Sometimes the given information goes beyond to what you could query synchronously in code, as is the case with promise objects. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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