求star

开源不易,喜欢请点个star吧

Ocean Han
890 字
4 分钟
完成一个判断数据类型的方法
2022-08-07

题目要求#

写一个返回数据类型的函数,如果自定义的类实例化的对象返回定义的类名

为什么不直接使用typeof判断#

typeof null会等于object,值得注意的是typeof (null)会返回Object,这是因为JS二进制前三位都为0的话会被判断为Object类型,null的二进制表示是全0,自然前三位也是0,所以执行typeof时会返回Object,实际null为基本数据类型。

​ 而且对于 对象和数组来说,都会转换成object

​ 对于null,我们可以使用===来进行判断

​ 所以,typeof可以判断基本数据类型,但是难以判断除了函数以外的复杂数据类型

typeof 1 // 'number'
typeof '1' // 'string'
typeof null // 'object'
typeof undefined // 'undefined'

typeof [] // 'object'
typeof {} // 'object'
typeof function(){} // 'function'

instanceof是否能正确判断类型#

WARNING

instanceof是通过原型链来判断的,但是对于对象来说,Array也会被转换成Object,而且也不能区分基本类型stringboolean

    function Func() {}
    const func = new Func()
    console.log(func instanceof Func) // true
    
    const obj = {}
    const arr = []
    obj instanceof Object // true
    arr instanceof Object // true
    arr instanceof Array // true
    
    const str = "abc"
    const str2 = new String("abc")
    str instanceof String // false
    str2 instanceof String // true

基于以上结论,先完成一个简易的函数:#

function myTypeof(data) {
    const type = typeof data
    if(data === null)
        return 'null'
   	if(type !== 'object')
        return type
   	if(data instanceof Array)
		return 'array'
    return 'object'
}

constructor#

TIP

​ constructor 判断方法跟instanceof相似,但是constructor检测Object与instanceof不一样,constructor还可以处理基本数据类型的检测,不仅仅是对象类型。

注意:

  1. null和undefined没有constructor;
  2. 判断数字时使用(),比如 (123).constructor,如果写成123.constructor会报错
  3. constructor在类继承时会出错,因为Object被覆盖掉了,检测结果就不对了:
// 注意当出现继承的时候,使用constructor会出现问题
function A() {}
function B() {}
A.prototype = new B()	// A继承自B
console.log(A.constructor === B) // false
var C = new A()
console.log(C.constructor === A) // false
console.log(C.constructor === B) // true
//解决这种情况,通常是手动调整对象的constructor指向
C.constructor = A
console.log(C.constructor === A) // true
console.log(C.constructor === B) // false

Array.isArray()#

 Array.isArray([1, 2, 3]); // true
 Array.isArray({foo: 123}); // false
 Array.isArray("foobar"); // false
 Array.isArray(undefined); // false

正则判断#

TIP

​ 我们可以把对象和数组转成一个字符串,这样就可以做格式判断,从而得到最终的类型。

function myTypeof(data) {
    const str = JSON.stringify(data)
    if(/^{.*}$/.test(str)){
        return 'object'
    }
    if(/^\[.*\]$/.test(str)){
        return 'array'
    }
}

Object.prototype.toString.call()#

TIP

​ 之所以要这样调用toString方法,在之前的文章中已经提到过,是为了确保调用的是Object原型上的toString方法

​ 每个对象都有一个toString()方法,当要将对象表示为文本值或以预期字符串的方式引用对象时,会自动调用该方法。默认情况下,从Object派生的每个对象都会继承toString()方法。如果此方法未在自定义对象中被覆盖,则toString()返回[Object type],其中type是对象类型。所以就有以下例子:

   Object.prototype.toString.call(new Date()) // [object Date]
   Object.prototype.toString.call("1") // [object String]
   Object.prototype.toString.call(1) // [object Numer]
   Object.prototype.toString.call(undefined) // [object Undefined]
   Object.prototype.toString.call(null) // [object Null]

综上,封装出以下通用类型的判断方法:#

function myTypeof(data){
    var toString = Object.prototype.toString
    var dataType = data instanceof Element ? 'Element' : toString.call(data).replace(/\[object\s(.+)\]/,"$1")
    return dataType
}

获取实例化对象的类名#

TIP

​ 我们只需要对,上述获取的Object类型的数据,直接使用xx.constructor.name即可

最终实现:100:#

function myTypeof(data) {
    var toString = Object.prototype.toString;
    var dataType = data instanceof Element ? "Element" : toString.call(data).replace(/\[object\s(.+)\]/, "$1")

    if(dataType === 'Object'){
        return data.constructor.name
    }

    return dataType
};
完成一个判断数据类型的方法
https://blog.oceanh.top/posts/frontend/写一个判断数据类型的方法/
作者
Ocean Han
发布于
2022-08-07
许可协议
CC BY-NC-SA 4.0
最后修改时间
2024-08-10 10:08:49