typeof 与 instanceof 区别(判断数据类型)

78 阅读2分钟

typeof 与 instanceof 区别

判断数据类型的方式有很多,typeof 与 instanceof 是两个js提供的接口,那么它们都有什么优势和缺点呢?我们又如何去实现一个更完美的判断数据类型方式呢?

一、typeof

使用方式

  1. 指令式: typeof operand
  1. 函数调用式:typeof (operand) operand表示对象或原始值的表达式,其类型将被返回

返回值

  • 返回值为字符串,一般都是(number, boolean, string, function, object, undefined)为什么说一般呢,因为有个 Symbol 它的返回值是 symbol

  • 见过一道笔试题:typeof typeof(any) 他的结果是string ps : typeof 返回值为字符串

  • 对于 Array 、 Null 等特殊对象使用 typeof 一律返回 object, 这正是 typeof 的局限性。

  • typeof nullobject,但这只是JavaScript 存在的一个悠久 Bug,不代表null就是引用数据类型,并且null本身也不是对象

<script>
        let a, b, c, d, e, f, g, h,  i;
        a = [1, 2, 3, 4, 5];
        b = 1;
        c = "小七";
        d = false;
        f = null;
        e = new Date();
        g = undefined;
        h = function () {};
 
        console.log(typeof(a));//object
        console.log(typeof(b));//number
        console.log(typeof(c));//string
        console.log(typeof(d));//boolean
        console.log(typeof(e));//object
        console.log(typeof(f));//object
        console.log(typeof(g));//undefined
        console.log(typeof(h));//function
        console.log(typeof(i));//undefined
    </script>

缺点:可以判断基本数据类型(null 除外),但是引用数据类型中,除了function 类型以外,其他的也无法判断。

二、instanceof

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

使用方式

object instanceof constructor object为实例对象, constructor为构造函数

返回值

  • instanceof返回的是一个布尔值

举个栗子:

let a = new Array();
alert(a instanceof Array); // true
alert(a instanceof Object) // true
 
//如上, 会返回 true, 同时 alert(a instanceof Object) 也会返回 true;
 
// 这是因为 Array 是 object 的子类。
alert(b instanceof Array) // b is not defined
 
 
function Test() {};
var a = new test();
alert(a instanceof test) // true

根据instanceof的使用方式,其实我们是可以自己写一个出来的!

function myInstanceof(example,dataType){
    let proto = Object.getPrototypeOf(example)
    let prototype = dataType.prototype
    while(true){
        if(!proto) return false
        if(proto === prototype) return true
        else{
            proto = Object.getPrototypeOf(proto)
        }
    }
}

// 使用
console.log(myInstanceof('123',Array)); //false 
console.log(myInstanceof([1,2,3],Array)); //true

缺点: instanceof 可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型。

-------------------------------------------------------

行文到此,我们可以发现这两种方式都有自己的缺陷,那我们如何得到一个比较完美的解决方案呢

三、Object.prototype.toString

使用方式

Object.prototype.toString( { } ) 括号内写要判断的数据

返回值

  • 统一返回格式[object XXX]的字符串 XXX就是该数据的数据类型

完美解决方案:

function getType(obj){
   let type  = typeof obj;
   if (type !== "object") return type
   return Object.prototype.toString.call(obj).slice(8,-1); 
  }
}

getType([])     // "Array" typeof []是object,因此toString返回
getType('123')  // "string" typeof 直接返回