Binarus Binarus - 1 month ago 16
Javascript Question

Is Object.prototype.toString a function or a property?

Before asking, I have tried to do my homework and to avoid a duplicate. Thus, I have read about 20 questions and answers (mainly on SO) which all deal with toString(). But unfortunately, none of them did answer my actual question. So here we go ...

Many examples contain code like that:

Object.prototype.toString.call(someVariable);


I just would like to know why
toString
can be used like a property here. I have read the reference for
Object.prototype
at MDN and other places. All of them list a function
toString()
among the members of
Object.prototype
, but no property
toString
.

Furthermore, I am using a line like that shown above at several places in my code. For testing purposes, I have added parentheses to make it "clean":

Object.prototype.toString().call(someVariable);


Obviously, that did not make it "clean", but just made it return wrong results or even made the browser stall (I am currently in the process of researching what exactly is going on).

I already have read some questions and answers regarding calling functions without parentheses. But even if I accept that the first of the code lines shown above actually calls a function (although it looks like accessing a property), that still does not explain why it goes wrong horribly when I add the parentheses as shown in the second code line. Being able to call functions without parentheses should not mean being unable to call them with parentheses, should it?

I don't think that question has an answer already (if yes, I apologize), so could anybody please give a short explanation?

Answer Source

Functions are just values. toString is a property of the Object.prototype object whose value is a function.

() is the function call operator. Object.prototype.toString doesn't call a function; it just fetches the value of the Object.prototype.toString property (which happens to be a function).

Functions are also objects, with properties of their own. That's why you can do Object.prototype.toString.call(...): This gets the Object.prototype.toString function, then fetches its call property, then calls it (which is allowed because the value of call is another function).

This works even without involving properties:

var foo = function () { return "hello"; };
var bar = foo;
console.log(bar);
console.log(bar());

The first line assigns a function value to the foo variable.

The second line assigns the same value to bar, reading from foo. Note that we're not calling the function, we're just passing it around like any other value.

The first console.log displays the function itself.

The second console.log displays the result of calling the function, because we used ().