Object.prototype.toString获取数据类型

92 阅读2分钟

为什么不能使用typeof去获取类型?

类型结果
Undefined"undefined"
Null"object"原因
Boolean"boolean"
Number"number"
BigInt"bigint"
String"string"
Symbol"symbol"
Function(在 ECMA-262 中实现 [[Call]];classes也是函数)"function"
其他任何对象"object"

可以看到使用typeof是有局限性的。null 会被判定为 “object” 其他任何对象(array date等)都会判定为“object”,这是不严谨的。 使用Object.prototype.toString()方法则能准确的获取到调用toString()方法的类型。

Object.prototype.toString的返回值

首先我们需要知道Object.prototype.toString是什么? 他就是Object原型对象上绑定的一个方法,所有基于Object创建的类型都能够顺着原型链向上找到toString方法.

Object.prototype.toString()
'[object Object]'

可以看到Object.prototype.toString()返回值是Object 这是因为Object.prototype本身是一个对象,记住他的核心:返回调用者的数据类型

当我们需要判定其他数据类型时,需要使用call改变this的指向问题:

Object.prototype.toString.call([])
'[object Array]'
Object.prototype.toString.call({})
'[object Object]'
Object.prototype.toString.call(1)
'[object Number]'
Object.prototype.toString.call("1")
'[object String]'
Object.prototype.toString.call(function(){})
'[object Function]'
Object.prototype.toString.call(/d+/)
'[object RegExp]'

核心:返回调用者的数据类型。可以看到当我们改变了this(改变调用者),则能准确的拿到调用者的类型。

那为什么不能使用每种类型的toString()呢?

image.png

控制台打印{} 或者 [] 都能看到__poto__上绑定的toString方法,直接使用会怎样?

使用每种数据类型的各自的toString方法

let arr=[1,"2",[1,2],{1:2}]
arr.prototype.toString()
'1,2,1,2,[object Object]'

Number.prototype.toString.call({})
VM3674:1 Uncaught TypeError: Number.prototype.toString requires that 'this' be a Number
    at Object.toString (<anonymous>)
    at <anonymous>:1:27
    
String.prototype.toString.call([])
VM3701:1 Uncaught TypeError: String.prototype.toString requires that 'this' be a String
    at Array.toString (<anonymous>)
    at <anonymous>:1:27

可以看到,每种数据类型上的toString都和Object.prototype.toString表现不一样,数组则是将元素转换为字符串,内部对象转成[object Object],而Number传入{}直接报错. 由此可见,每种类型的toString都是被重新定义过的,只适用于当前类型

array.prototype.toString()相对特殊

Array.prototype.toString.call({}); <!--"[object Object]"--> 
Array.prototype.toString.call(function(){}) <!--"[object Function]"--> 
Array.prototype.toString.call(1) <!--"[object Number]"--> 
Array.prototype.toString.call('1')<!--"[object String]"-->

表现基本和Object.prototype.toString相似,但是this指向null和undefined时表现不同:

Object.prototype.toString.call()
'[object Undefined]'
Object.prototype.toString.call(null)
'[object Null]'


Array.prototype.toString.call()
VM4071:1 Uncaught TypeError: Cannot convert undefined or null to object
    at toString (<anonymous>)
    at <anonymous>:1:26
(anonymous) @ VM4071:1
Array.prototype.toString.call(null)
VM4105:1 Uncaught TypeError: Cannot convert undefined or null to object
    at toString (<anonymous>)
    at <anonymous>:1:26

所以使用Object.prototype.toString更加准确一些

toString()

可以在控制台直接输入toSting看执行情况

toString(1)
'[object Undefined]'
toString({})
'[object Undefined]'

本质上就等于 Object.prototype.toString.call() 或 Object.prototype.toString.call(undefined) 你也可以使用toString.call()去代替使用Object.prototype.toString.call() 【不建议,可能window中会复写toString】

toString.call({})
'[object Object]'
toString.call([])
'[object Array]'

如果没有在window中复写toString 则直接调用toString方法或者使用window.toString方法就等于使用Object.prototype.toString

如果复写:

let toString=function(){console.log('1111')}
toString.call()
1111
toString.call(222)
1111

可以看到输出的是复写后的内容