Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lost with the output of "constructor.name" in javascript

I had a similar condition required to check if the String type constructor name is "String" or "string".

I am lost with outputs of following JS code:

(typeof([].constructor.name)).constructor.name
"String"

typeof([].constructor.name).constructor.name
"string"

But when I test output of following code I get more confused:

(typeof([].constructor.name))
"string"

typeof([].constructor.name)
"string"

"string".constructor.name
"String"

According to my understanding the output should always be "String".

Can anyone put some bright light on what I am missing or whats going wrong with above code?

like image 456
Amol M Kulkarni Avatar asked Oct 31 '22 02:10

Amol M Kulkarni


1 Answers

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

like image 116
Mauricio Poppe Avatar answered Nov 08 '22 07:11

Mauricio Poppe