A possible reason
After playing with the console I found the following, it seems like typeof(a).b
might be equivalent to typeof (a).b
so it seems like the following are equivalent
(typeof([].constructor.name)).constructor.name
(typeof [].constructor.name).constructor.name
However for the second example it seems like the following is executed
typeof([].constructor.name).constructor.name
typeof ([].constructor.name).constructor.name
The second parenthesis in the first example is acting as a grouping operator and that might be the reason of the weird results
Regarding the "string"
and "String"
values
As you may already know we can access the name of a named function through the name
property
function A(){}
A.name // A
Also when you create a function behind the curtains an object is created which is accessible through the function's prototype
property, this object has a reference to the function itself through its constructor
property
function A(){}
A.prototype // {constructor: A}
A.prototype.constructor === A // true
Whenever you create an "instance" of a function its hidden [[Prototype]]
property (aka __proto__
) points to the prototype of the constructor so
[].__proto__ === Array.prototype // true
Since an empty array doesn't have the property constructor
defined on it, JS looks in the object pointed by __proto__
which for the empty array as seen above is the Array.prototype
which has a constructor
property therefore
[].constructor === Array // true
From this place the resolution of the operand gets trivial
[].constructor.name // "Array"
[].constructor.name.constructor === String // true
[].constructor.name.constructor.name // "String", i.e. the name of the `function String() {}`
So in your examples
(typeof [].constructor.name).constructor.name
// evaluated to
(typeof "Array").constructor.name
// evaluated to
"string".constructor.name
// evaluated to
String.name
// evaluated to
"String"
And for the second example
typeof ([].constructor.name).constructor.name
// evaluated to
typeof "String"
// evaluated to
"string"
Moral of the story: use typeof operator
instead of typeof()
.