Does javascript coerce numbers to string to print in the console?

Hi !
I was just reading a book on javascript and got confused in this sentence.

var x = 99.99;
console.log( x );

So x is a number in this case, in second line when javascript prints it on the console will it coerce to a string ? If yes then why ? Can’t javascript print just numbers on the console?

Kindly anyone help anyone to clear this doubt !

1 Like

console.log() converts the arguments passed to it into strings.

It seems to implement arguments.toString().

2 Likes

Why does it convert arguments into strings ? Can’t it just print the argument to the console ?

1 Like

JavaScript won’t coerce your number to a string, you can see that when you console.log(4) and console.log('4'). The first prints in blue (at least in Chrome’s developer tools), because it’s a number. The second prints in black, because it’s a string.

There are instances though when you try to log an object, or a function. That’ll be coerced to a string to make it readable. It won’t change the object, though. You’ll never have to worry that your console.log does anything weird to your code, it just logs.

2 Likes

I don’t think that console.log coerce numbers to strings:

Chrome
chrome

Firefox
firefox

2 Likes

Additionally, I think what I said above about objects and functions being coerced to strings isn’t true, either. At least not with Object.prototype.toString. Formatting of the output of console.log probably depends on the environment that JS is running in, but in any case, it’s just formatting, not coercion.

3 Likes

Yes it converts it to a string, but why is that relevant? It needs to convert it to a string because that’s what console functions print: strings. But if you log

99.99

then what you see is

99.99

It’s just a set of characters printed on a screen. The fact that the function (console.log) does this by converting whatever you give it to a string isn’t really relevant: all it’s doing is displaying some characters. You can’t do anything with it: it’s completely static, it’s just a string that is passed to the underlying functions that render it in the debug console.

That’s…what it’s doing. A number in a mathematical sense is an idea of quantity. A number in a human-readable sense is some characters strung together to represent that idea. A collection of characters printed on a screen normally uses a string datatype to represent that collection of characters

For reference:

https://source.chromium.org/chromium/chromium/src/+/master:out/Debug/gen/devtools/common/Console.js;l=43?q=console.log&sq=&ss=chromium

4 Likes

Yeah ! I just noticed Numbers are displayed in blue and string are in black in chrome dev tool. So why does the book say it ? Can I see the actual code of log() method?

1 Like

The actual code of log is at the attached link?

2 Likes

Yeah ! The code is

    log(text)
   {
        this.addMessage(text, MessageLevel.Info);
   }

can you please tell me what’s the code for addMessage() ?

1 Like

Is this it?
https://source.chromium.org/chromium/chromium/src/+/master:components/messages/android/java/src/org/chromium/components/messages/MessageContainer.java;l=30?q=addMessage&sq=&ss=chromium
Hmm, no that one takes a view?
Nope, you just want line 35 of the first link.

    addMessage(text, level, show) {
        const message = new Message(text, level || MessageLevel.Info, Date.now(), show || false);
        this._messages.push(message);
        this.dispatchEventToListeners(Events.MessageAdded, message);
    }

To be honest, I just used the search feature at the top of the page.


Note that the relevant piece to your question is that console.log always takes a string argument, so if the argument is not a string, the argument has to be represented as a string.

2 Likes

Yeah ! I got it Thank you Everyone :slight_smile:

1 Like

This one is a bit complecated for me to understand :face_with_raised_eyebrow:

1 Like

There is a function called Message defined somewhere else that creates an object, then that object gets pushed to some array that exists on the parent object, then a function defined somewhere on the parent object is called. It’s not really relevant to the question, it’s just the underlying JS mechanism of the console printer functionality + general messaging functionality for the debug console. You have to keep going back through functions – nothing on its own there is complicated, it’s just that there are hundreds and hundreds of thousands of lines of similar code.

2 Likes

I’m currently trying to make sense of some fundamentals - can you maybe explain in simple words why Object.prototype.toString isn’t called anywhere? Is the above code part of the runtime, and the Object prototype lives in the engine?

1 Like

Doesn’t need to – JS coerces it to a string. To clarify, this isn’t part of the runtime engine (v8), this is a browser API – it’s just standard JS code. The browser engine (Blink) is written in C++ (as with v8), and this is just a JS interface into this, and the logging part of the C++ code (which is part of the I/O functionality) casts to a string – it’s an external module and I can’t get it up in the browser, but it’s imported here:

https://source.chromium.org/chromium/chromium/src/+/master:extensions/renderer/console.h;l=17;bpv=0;bpt=1

Edit: how it pretty-prints objects I don’t know, I haven’t dug that far. Possibly some metatadata is accessed on all objects (including primitive wrappers?) in the context of the debug console before it is coerced to a string, I don’t know (or the toString methods are overridden for each type in that context, not sure).

2 Likes

Thanks for explaining, not sure if I understood everything but on a side note, I’ve learned that each type (Object, Function, Number…) has its own .toString method. The only one that gets called by the console is when you log a function.

For what it’s worth, here’s what I did - made some simple test examples, then messed with the Prototype and then logged them out:

const obj = {'one':'two'};
const func = () => 'HI';

Object.prototype.toString = () => 'objToString() is currently not available';
Function.prototype.toString = () => 'funcToString() is currently not available';

console.log(obj); // {one: "two"}
console.log(func); // funcToString() is currently not available

I’ll put the internal workings aside for now, don’t think I could even read C++ code.

1 Like

Yes, there is the toString method defined on object prototype. Then, because each type is slightly different, it is overridden if necessary. It’s fairly common to define a toString method for classes so that they can print out detailed information specific to the class when logging.

Re not understanding the C++ code: I don’t use it either but I’m inferring what it does. The browser, everything it does, it’s written in that. The console functions are just there to transfer a string to the underlying functions that need it. The functions take some string and pass it to the code that actually does things. JS is just a scripting layer, and in this case the implementation seems extremely simplistic, the JS part barely does anything.

1 Like