Why does console.log log strings with quotes in some cases? - javascript

I am running these examples of Node.js v10.5.0. When I only print strings with it, it prints the strings without surrounding quotes.
> console.log('foo', 'bar')
foo bar
undefined
But when I print strings and numbers together, then it prints strings with surrounding quotes.
> console.log(1, 'foo', 'bar')
1 'foo' 'bar'
undefined
Why does this difference occur? I was expecting it to print the following in the second example:
1 foo bar
Similar behavior can be observed with Chrome 70.
It looks like console.log() chooses to show string in quotes when there are arguments of number type but then these examples print all strings without quotes even when numbers are involved:
> console.log('foo', 'bar', 1)
foo bar 1
undefined
> console.log('foo', 1, 'bar')
foo 1 bar
undefined
What's going on here? Why does console.log() print strings with quotes in some cases and not in other cases?

This seems like a deliberate choice by the Chrome team. There is no standard for how console.log works in different environments.

There's not a legitimate standard yet for console.log but most browsers, including Chrome (i.e. Chromium), use the working group specification (WHATWG):
https://console.spec.whatwg.org/#logger
According to this spec, if you have differing numbers of parameters then different methods are used to output the data, according to the current specification:
2.1 Logger(logLevel, args)
If args is empty, return.
Let first be args[0].
Let rest be all elements following first in args.
If rest is empty, perform Printer(logLevel, « first ») and return.
If first does not contain any format specifiers, perform
Printer(logLevel, args).
Otherwise, perform Printer(logLevel, Formatter(args)).
Return undefined.
Ultimately, the number of parameters determine the methods that are used to output information. Specifically, in your example the first parameter can not contain a format specifier because it's a number so it gets passed to Printer() but if the first parameter is a string then it gets passed to Formatter().
So, you get different output depending on order:
> console.log('hello',1,'hello')
hello 1 hello
versus
> console.log(1,'hello','hello')
1 "hello" "hello"
Ultimately, how those methods output information is implementation/browser dependent:
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.

Related

Javascript String Array-Like-Object behaviour

When I run above code in Chrome dev console, I do not get any error. But when same code runs via js loaded on a webpage I receive this exception -
Cannot create property 'name' on string 'some string'
Can someone please tell me why there is different behaviour in above 2 cases?
Your webpage must be running that snippet of code in strict mode, in which assigning to properties of a string will throw an error:
'use strict';
const str = 'foo';
str.bar = 'bar';
In sloppy mode, it'll just fail silently:
const str = 'foo';
str.bar = 'bar';
Strings are a value objects as in they have a value not a reference to an instance of an object, they cannot have properties set with a["name"] like reference objects can.
a[3] is the 4th character in the string, a[0] being the first.
Let's see this case
const a = "a"
Object.isFrozen(a) // true
const b = new String("b")
Object.isFrozen(b) // false
From this section, we could see that String objects are not necessarily frozen. Only those string literals are frozen (I think it's because they are shared in a pool. If they are not frozen, you can create properties on one place to affect the code elsewhere) However, the explicitly constructed String objects are independent from the pool, thus not frozen.

Console.log vs printing out variable

How come when I use console.log to print out a value in the console window for a string it is not in quotes, but when I just output the variable in the console, it prints quotes. Is there any particular reason for this?
var test = “hello”;
test;
Output : “hello”
Console.log(test);
Output: hello
Well , see like this.
var test = "hello";
test; // This is object in self and what is it,
// it is a string in literal
// Output comes only from debugger , when you input direct.
// test; this line have no output to the console
// Output : "hello" NO
//console.log(test); // console.log already print string (in native/string is output) but also print objects.
// Output: hello YES
console.log( test + " this is the test")
// See output it is a very clear
// hello this is the test
The default behavior is for strings to be represented along with quotes in the console.
a = 'hi';
a
// returns "hi"
The console api is different and an exception.
console.log(object [, object, ...])
Displays a message in the console. Pass one or more objects to this method. Each object is evaluated and concatenated into a space-delimited string.
So it returns a space-delimited, concatenated string. Which means it will always be a string. Since its always a string, we can do away with the quotes. I suppose the console devs let it be that way to make the point that console.log() will always return the same type (string). Adding quotes might imply the possibility that it could return other things, so it seems to be a UX thing for the console.
Javascript is dynamically typed which means a variable can store any type of value at any time. If you call a variable storing a string (which is test in your case) it prints out the value "Hello" indicating its a string and returns a string datatype, which is preety straightforward. But numbers can also be strings like var a = "5". On the other hand console.log() simply prints the value inside the variable and by default returns undefined.
var a = "hello";
// To check the return type of variable a which is string
console.log(typeof(a));
// To check the return type of console.log() which is undefined
console.log(typeof(console.log(a)));

Named array element used in function definition

Recently I discovered that this syntax works in JavaScript (Chrome 53):
function foo([param1]) { // Function argument is declared as array and param1 is used as variable? What is the name of this syntax?
console.log(param1);
}
foo(['TestParameter1']); // Case 1 - works. Output: TestParameter1
foo('TestParameter1'); // Case 2 - works??? Why? Output: TestParameter1
foo(123); // Case 3 - does not work - VM860:1 Uncaught TypeError: undefined is not a function(…)
Result => TestParameter1 // this is the result
I see that param1 can be used as variable that references item with index 0 in the first argument (declared as array).
My questions are:
1) How is this syntax named (the [param1] part that lets you use param1 as variable)?
2) Why does "Case 2" work? Is there any automatic conversion?
As #Xufox pointed out, this works because of destructuring (array destructuring, to be more specific). Your second example works because a string is an array-like object, so you get T, which is param1[0]. Numbers are not arrays (or even array-like), so the the engine fails to destructure the argument.
If you coerce your number to a string it will work:
foo((123).toString());
This seems to be destructuring as #Xufox correctly pointed out.
Function parameters can in fact have destructuring:
go to https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
Search for this text: Pulling fields from objects passed as function parameter
Now the above shows an example of another kind of destructuring, example given below:
function userId({id}) {
return id;
}
var user = {
id: 42,
displayName: "jdoe"
};
console.log("userId: " + userId(user)); // "userId: 42"
however, I assume it applies to this as well:
function foo([param1]) {
console.log(param1);
}
Difference between integers and strings in this behaviour:
console.log('123'); //works, outputs 1, '123' = ['1', '2', '3'] of chars
console.log(['123']); //works, outputs 123
console.log([123]); //works, outputs 123
console.log(123); //error
In the above example, since strings are nothing but an array of chars, its perfectly fine that it works actually.
Exactly as said by those brilliant folks above. Here's how the computer reads it:
foo('testParamater1') = foo(['testParamater1']);
but...
foo(123) = foo([[1,2,3]);
Unfortunately for your specific use case, not the same. Sorry!

JavaScript regex - null argument makes the regex match

I'm writing a regex to be used with JavaScript. When testing I came across some strange behavior and boiled it down to the following:
/^[a-z]/.test("abc"); // <-- returns true as expected
/^[a-z]/.test(null); // <-- returns true, but why?
I was assuming that the last case was going to return false since it does not meet the regex (the value is null and thus, do no start with a character in the range). So, can anyone explain me why this is not the case?
If I do the same test in C#:
var regex = new Regex("^[a-z]");
var res = regex.IsMatch(null); // <-- ArgumentNullException
... I get an ArgumentNullException which makes sense. So, I guess when testing a regex in JavaScript, you have to manually do a null check?
I have tried searching for an explanation, but without any luck.
That's because test converts its argument : null is converted to the "null" string.
You can check that in the console :
/^null$/.test(null)
returns true.
The call to ToString(argument) is specified in the ECMAScript specification (see also ToString).
Here null is getting typecasted to String form which is "null".
And "null" matches your provided regex which is why it is evaluating to true
In Javascript, everything(or mostly) is an Object which has ToString method which will be automatically called upon internally in case there is a need for a typecast.

IE8 Javascript: '2' is null or not an object

I'm getting a nonsensical error message in IE8, tell me that the constant '2' is null or not an object. The line of code is:
if (! localtree[idx][2]) {
I also tried coding it like this:
if (localtree[idx][2] == 0) {
The value in the array at that location is always zero (for now).
How can IE8 think that the number 2 is null? I'm mystified!
The exact error is:
Message: '2' is null or not an object
Has anyone seen this?
EDIT : This is a very misleading error message. See my answer below for what actually went wrong.
This is a very confusing error message. It turned out that I was stepping one element beyond the end of the array. 'idx' was referencing a non-existent value that I was attempting to treat as an array reference (with the [2]).
Rather than telling me that '2' was null, it should have said that 'localtree[idx]' was null.
The root cause of this was that I had a trailing comma where I defined the array, leading to an extra, null value in the array. In firefox, trailing commas are ignored (like in perl), but in IE, they are significant.
the constant '2' is null or not an object
if (! localtree[idx][2]) {
JavaScript doesn't have constants, at least not yet. And you aren't checking a number, but a member of an array, i.e.: the variable with index number 2 of object localtree[idx] (where idx must contain a string to refer to an object property or an index number to refer to an array).

Categories