Let's say we do this:
function Dog(name, breed) {
this.name = name;
this.breed = breed;
}
var date = new Date();
var dog = new Dog("YOU'RE", "READING");
var zehbi = Object.prototype.toString.call(date);
var zehbi2 = Object.prototype.toString.call(dog);
console.log(zehbi);
console.log(zehbi2);
Why does zehbi return the name of its constructor function "Date" but zehbi2 doesn't return the name of it's constructor function "Dog" but returns "Object" instead?
Because it is defined that way in the specification:
20.1.3.6 Object.prototype.toString ( )
When thetoStringtoString method is called, the following steps are taken:
- If the
thisvalue isundefined, return "[object Undefined]".- If the
thisvalue isnull, return "[object Null]".- Let
Obe ! ToObject(this value).- Let
isArraybe ? IsArray(O).- If
isArrayistrue, letbuiltinTagbe "Array".- Else if
Ohas a[[ParameterMap]]internal slot, letbuiltinTagbe "Arguments".- Else if
Ohas a[[Call]]internal method, letbuiltinTagbe "Function".- Else if
Ohas an[[ErrorData]]internal slot, letbuiltinTagbe "Error"`.- Else if
Ohas a[[BooleanData]]internal slot, letbuiltinTagbe "Boolean".- Else if
Ohas a[[NumberData]]internal slot, letbuiltinTagbe "Number".- Else if
Ohas a[[StringData]]internal slot, letbuiltinTagbe "String".- Else if
Ohas a[[DateValue]]internal slot, letbuiltinTagbe "Date".- Else if
Ohas a[[RegExpMatcher]]internal slot, letbuiltinTagbe "RegExp".- Else, let
builtinTagbe "Object"- Let
tagbe ?Get(O, @@toStringTag).- If
Type(tag)is notString, settagtobuiltinTag.- Return the string-concatenation of "[object ", tag, and "]".
And for Date the point 12. is true because it has an [[DateValue]] internal slot, your Dog does not match any of the 5. to 13. so 14. is used. After that 15. checks for the existence of @@toStringTag which does not return a string for Dog or Date, so the tag becomes the builtinTag given by one of the 5. to 14..
The result of Object.prototype.toString() is determined by two things:
"[object Date]".@@toStringTag.For the normal objects, prior to ES6 the default toString() would only produce "[object Object]" while post ES6 the result is the string "[object @@toStringTag]" by using the value of the symbol. By default the value for the symbol is "Object".
You can override it for a custom class:
function Dog(name, breed) {
this.name = name;
this.breed = breed;
}
Dog.prototype[Symbol.toStringTag] = "Dog";
var dog = new Dog("YOU'RE", "READING");
var zehbi2 = Object.prototype.toString.call(dog);
console.log(zehbi2);
Or any object:
var obj = {
[Symbol.toStringTag]: "Custom"
}
console.log(Object.prototype.toString.call(obj));
console.log(obj.toString());
You can even override it for built-in objects:
var obj = new Date()
obj[Symbol.toStringTag] = "Custom";
console.log(Object.prototype.toString.call(obj));