美文网首页深究JavaScript前端Web前端之路
Javascript 中的变量类型判断

Javascript 中的变量类型判断

作者: 苏敏 | 来源:发表于2018-04-05 23:32 被阅读17次

    熟悉 JavaScript 数据类型的话我们知道在 JavaScript 这门语言中存在基本类型(值类型),如Undefined ,Null,Boolean,Number,String,可以类比数据结构中只有栈内存而没有堆内存;还有一种就是引用类型,如Function,Array,Object, Date, RegExp,同理在数据结构中既有栈内存也有堆内存,栈内存中是存放的一个堆内存的引用,也可以理解为指针。这里暂时不讨论包装类型,因为它也算是引用类型的一种。还有一个要注意的地方,String 类型在 Java 中是属于引用类型,但是 JavaScript 里面看做了基本类型。

    这里我们要判断一个变量是不是基本类型或者引用类型该怎么做呢?聪明的你肯定能立马想到:简单类型的类型判断用 typeof,引用类型的类型判断用 instanceof。我们看一下代码,

    console.log(typeof x);      // undefined
    console.log(typeof 10);     // number
    console.log(typeof 'abc');  // string
    console.log(typeof true);   // boolean
    console.log(typeof null);   // object  这是错误的
    
    
    console.log(Function instanceof Object);      // true
    console.log(Object instanceof Function);      // true
    console.log(Function instanceof Function);    // true
    

    我们发现基本类型时候其他都正常但是 Null 是指向了 object,这是为啥呢?还有下面的 instanceof 三个都是 true,好奇怪啊,但是自己去运行一下还真的是正确的?这又是为啥呢?带着疑问我们继续往下走。

    首先看一下为啥 typeof null 报的是 object,参考 ECMA 中规定,里面规定了 typeof(null) 的值是"object",但是为什么在有 Null type 的情况下不返回 "null" 呢?我上知乎找了下仅供参考:


    image.png

    基于这个原因所以我们只用 typeof 判断除了 null 的基本类型

    我们接着来看一下 instanceof 如何判断的 ,

    a instanceof A
    
    沿着 a 的 __proto__ 这条线来找,同时沿着 b 的 prototype 这条线来找,
    如果两条线能找到同一个引用,即同一个对象,那么就返回 true 。
    如果找到终点还未重合,则返回 false 。
    

    通过JavaScript的原型链可以找到同一个对象,所以上面的三条记录都是true,并且因为 instanceof 沿着原型链查找,所以无法判断基本类型,根据这个规则以及下面的图示我们来快速理解一下


    image.png

    其实除了上面的 typeof 以及 instanceof 之外,我们还可以通过另外两种更强大的类型检测方法,那就是 Object.prototype.toString.call 以及 Constructor,如果有阅读过源码的话我们就能发现,源码中检测类型一般用到的是 Object.prototype.toString.call,我们来看一下代码中这两种是如何判断的

    let test = function() {}
    console.log(Object.prototype.toString.call(test))    // [object Function]
    
    let test = [1, 2, 3]
    console.log(Object.prototype.toString.call(test))    // [object Array]
    
    let test = Null
    console.log(Object.prototype.toString.call(test))    // [object Null]
    
    let test = undefined
    console.log(Object.prototype.toString.call(test))    // [object Undefined]
    
    let test = '123e'
    console.log(Object.prototype.toString.call(test))    // [object String]
    
    ...       // 经过测试我们发现他能满足基本类型和引用类型,很强大~
    

    constructor 属性: JavaScript 中,每个对象都有一个 constructor 属性,它引用了初始化该对象的构造函数,常用于判断未知对象的类型。这也是一个很强大的方法,不过不适用于 null 和 undefined, 我们还是看控制台输出,

    let aa = null 
    aa.constructor()      // undefined 和 null 报错
    
    let test = '123e'
    test.constructor()    // ""
    
    let arr = [1,2,3,4]
    arr.constructor()      // []
    
    let func = function(){}
    func.constructor()     // ƒ anonymous() {}
    
    let aa = new RegExp
    aa.constructor()       //  /(?:)/
    
    ....   // 由于 对象 存在构造函数这个属性,所以我们也可以很方便去通过这个来判断类型
    

    总结一下:

    我们判断基本类型可以通过 typeof 简单判断,当然是用 Object.prototype.toString.call 更加精准,日常开发中也推荐使用~ 内置对象就是我们经常用到的Array、 Math、 RegExp 以及 Date 等等,这种类型我们不能用 typeof 只能使用其他三种方式去判断;自定义对象就是我们自己通过 new 或者 Object.create() 等等创建出来的对象(这个也可以单独拿出来讲,不过还是下次对比不同创建对象方式以及继承的差异性里面讲),这种自定义的对象我们可以使用 instanceof 以及 Constructor 构造函数去做类型检测,下面是一个图示对比

    image.png

    相关文章

      网友评论

      本文标题:Javascript 中的变量类型判断

      本文链接:https://www.haomeiwen.com/subject/qindhftx.html