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?
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.
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.
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
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?
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.
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.
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?
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:
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).
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.
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.