头图

之前只知道Object.prototype.toString.call()可以用来判断数据类型,但是从未想过其原理,今天查资料的时候发现MDN上写的明明白白。

toString方法

一句话理解:.toString方法将对象转为一个原始值

JavaScript 调用 toString 方法将对象转换为一个原始值。你很少需要自己去调用 toString 方法;当遇到需要原始值的对象时,JavaScript 会自己调用它。

该方法由字符串转换优先调用,但是数字的强制转换和原始值的强制转换会优先调用 valueOf()。然而,因为基本的 valueOf() 方法返回一个对象,toString() 方法通常在结束时调用,除非对象重写了 valueOf()。例如,+[1] 返回 1,因为它的 toString() 方法返回 "1",然后将其转换为数字。

Object.prototype.toString

一句话理解:Object.prototype.toString() 返回 "[object Type]"

所有继承自 Object.prototype 的对象(即,除了 null-prototype 对象之外的对象)都继承 toString() 方法。当你创建一个自定义对象时,你可以重写 toString() 以调用自定义方法,以便将自定义对象转换为一个字符串。或者,你可以增加一个 @@toPrimitive 方法,该方法允许对转换过程有更多的控制,并且对于任意的类型转换,且总是优先于 valueOf 或 toString。
Object.prototype.toString() 返回 "[object Type]",这里的 Type 是对象的类型。如果对象有 Symbol.toStringTag 属性,其值是一个字符串,则它的值将被用作 Type。许多内置的对象,包括 Map 和 Symbol,都有 Symbol.toStringTag。一些早于 ES6 的对象没有 Symbol.toStringTag,但仍然有一个特殊的标签。它们包括(标签与下面给出的类型名相同):

  • Array
  • Function(它的 typeof 返回 "function")
  • Error
  • Boolean
  • Number
  • String
  • Date
  • RegExp

arguments 对象返回 "[object Arguments]"。其他所有内容,包括用户自定义的类,除非有一个自定义的 Symbol.toStringTag,否则都将返回 "[object Object]"。

在 null 和 undefined 上调用 Object.prototype.toString() 分别返回 [object Null] 和 [object Undefined]。

Object.prototype.toString.call

要将基本的 Object.prototype.toString() 用于重写的对象(或者在 null 或 undefined 上调用它),你需要在它上面调用 Function.prototype.call() 或者 Function.prototype.apply(),将要检查的对象作为第一个参数传递(称为 thisArg)。

const arr = [1, 2, 3];

arr.toString(); // "1,2,3"
Object.prototype.toString.call(arr); // "[object Array]"

使用toString方法检测类型的不可靠性

一般来说通过toString你可以获得它的类,但是这种方式也不一定是可靠的。
前面提到,Object.prototype.toString 返回"[object Type]",这里的 Type 是可以认为是Symbol.toStringTag的值。
但是这个值是可以改的,这就导致其结果不一定可靠。例如:

const myDate = new Date();
Object.prototype.toString.call(myDate); // [object Date]

myDate[Symbol.toStringTag] = "myDate";
Object.prototype.toString.call(myDate); // [object myDate]

Date.prototype[Symbol.toStringTag] = "prototype polluted";
Object.prototype.toString.call(new Date()); // [object prototype polluted]

参考文档


aqiongbei
2k 声望283 粉丝

人生路上,你走的每一步都算数