MDN上的解释为:
Symbol.toStringTag是一个内置symbol,它通常作为对象的属性键使用,对应的属性值应该为字符串类型,这个字符串用来表示该对象的自定义类型标签,通常只有内置的Object.prototype.toString()方法会去读取这个标签并把它包含在自己的返回值里。
也就是说,这个属性定义了Object.prototype.toString()方法的返回值。
我们先看Object.prototype.toString()方法。
Object.prototype.toString()
mdn上对Object.prototype.toString()的解释为:
Object.prototype.toString()返回一个表示该对象的字符串。
每个对象都有一个toString()方法,当该对象表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。
默认情况下,toString()方法被每个Object对象继承,如果此方法在自定义对象中未被覆盖,toString()返回“[object type]”,其中type是对象的类型。
var toStringFunc = Object.prototype.toString
toStringFunc.call(new Date) // '[object Date]'
toStringFunc.call(new String) // '[object String]'
toStringFunc.call(Math) // '[object Math]'
toStringFunc.call(undefined) // '[object Undefined]'
toStringFunc.call(null) // '[object Null]'
也可以自定义一个方法,来覆盖默认的toString()方法。该toString()不能传入任何参数,并且必须返回一个字符串。自定义的toString()方法可以是任何我们需要的值,但如果它附带有关对象的信息,它将变得非常有用。
function Dog(name, color) {
this.name = name
this.color = color
}
var dog = new Dog('Gabby', 'white')
// 默认的toString()
dog.toString() // '[object Object]'
// 覆盖默认的toString()
Dog.prototype.toString = function () {
return `Dog${this.name} is ${this.color}`
}
dog.toString() // 'Dog Gabby is white'
Symbol.toStringTag
前面说到,Symbol.toStringTag其实是定义了Object.prototype.toString()方法的返回值。以Map为例,Object.prototype.toString.call(new Map())的返回值通常是'[object Map]',这个Map就是存储在Symbol.singleTag这个键中的值。
但是并不是所有的对象都有toStringTag属性,没有toStringTag属性的某些对象也能被toString()方法识别并返回特定的类型标签。比如:
let toStringFunc = Object.prototype.toString
toStringFunc.call('foo') // '[object String]'
toStringFunc.call([1, 2]) // '[object Array]'
toStringFunc.call(3) // '[object Number]'
toStringFunc.call(true) // '[object Boolean]'
toStringFunc.call(undefined) // '[object Undefined]'
toStringFunc.call(null) // '[object Null]'
另外一些对象的类型toString()方法能识别它们就是因为引擎为它们设置好了toStringTag标签,toString()会返回Symbol.toStringTag键对应的值。比如上面提到的Map,还有:
Object.prototype.toString.call(function* () {})
// '[object GeneratorFunction]'
Object.prototype.toString.call(Promise.resolve())
// '[object Promise]'
但自己创建的类不会有这份特殊待遇,toString()找不到toStringTag属性时只好返回默认的Object标签。
class TestToStringTagClass {}
Object.prototype.toString.call(new TestToStringTagClass())
// '[object Object]'
加上toStringTag属性,自定义的类也会有自定义的类型标签了。
class TestToStringTagClass {
get [Symbol.toStringTag]() {
return "TestToStringTag"
}
}
Object.prototype.toString.call(new TestToStringTagClass())
// '[object TestToStringTag]'