OK I just did it and scratched my head for a while. I tried following on my Chrome console:
var a = [];
toString.call(a); //[object Array]
a.toString(); //""
toString(a); //[object Object] I know it's blunder but still!
What is difference between the toString and .toString I definitely know they are from different scopes (objects), but which one should be used at what time? Why is it so messy?
First of all we have to clarify that
toStringrefers toObject.prototype.toString:How
Object.prototype.toStringworks is explained in section 15.2.4.2 of the specification:toString.call(a)is the same asObject.prototype.toString.call(a)and works according to the above algorithm:thisrefers to the arraya(because you used.call), the internal[[Class]]property has the valueArray, hence the output is[object Array].a.toString(): Arrays overwrite thetoStringproperty, which is defined in section 15.4.4.2. In short, all array elements are concatenated and since the array is empty, you get an empty string as result.toString(a)is the same asObject.prototype.toString(). The argument is simply ignored. Thereforethisrefers toObject.prototype, which is an object and according to the algorithm mentioned above, the output is[object Object]. The output would be same for any value ofa.That depends on what you want to do. Personally I find none of the built-in
toStringfunctions particularly useful, besides for some quick and dirty debugging.Well,
Object.prototype.toStringandArray.prototype.toStringare simply two different methods, hence you get different results.You could argue that
Object.prototype.toStringshould call the overwrittentoStringif it exists, but that’s just not howtoStringis implemented.