美文网首页Javascript Web前端之路让前端飞
[JavaScript]typeof和instanceof的区别

[JavaScript]typeof和instanceof的区别

作者: 娜姐聊前端 | 来源:发表于2017-03-02 17:56 被阅读140次

    JS里面判断数据类型,一般用typeof或者instanceof两种方法,那么,两者到底有什么区别呢?

    1. typeof

    typeof用于基本数据类型的类型判断,返回值都为小写的字符串。如果是对象,除了function类型会返回“function”, 其他对象统一返回“object”。详情如下:

    typeof.png
    小贴士:
    
    JavaScript基本数据类型为:
    null, undefined, number, string, boolean, object
    

    2. instanceof

    instanceof 利用原型链继承关系做判断,它针对对象类型(格式:对象 instanceof 构造函数)。

    “尽管instanceof 运算符的右操作数是构造函数,但计算过程实际上是检测了对象的继承关系,而不是检测创建对象的构造函数 ”(摘自《JavaScript权威指南》)

    2.1 原型对象

    一旦创建一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,该属性指向函数的原型对象XXX.prototype。在默认情况下,所有原型对象会自动获得一个constructor属性,该属性指向这个函数。

    MDN上对原型上constructor的解释如下:

    Returns a reference to the Object constructor function that created the instance object. 
    Note that the value of this property is a reference to the function itself, not a string containing the function's name. 
    译文:返回一个指向创建了该对象原型的函数引用。
    需要注意的是,该属性的值是那个函数本身,而不是一个包含函数名称的字符串。
    

    所有的对象都有constructor属性。如果一个对象没有显性指定constructor值,那么它将指向原始构造函数。如下所示:

    var o = new Object;
    o.constructor === Object; //true
    
    var a = [];
    a.constructor === Array; // true
    
    var a = new Array;
    a.constructor === Array //true
    
    var n = new Number(3);
    n.constructor === Number; // true
    
    2.2 原型链继承

    下面是一个典型原型链继承:

    function SuperType() {
      this.property = true;
    }
    SuperType.prototype.getSuperValue = function    () {
      return this.property;
    };
    function SubType() {
      this.subproperty = false;
    }
    
    SubType.prototype = new SuperType();
    SubType.prototype.getSubValue = function    () {
      return this.subproperty;
    };
    var instance = new SubType();
    

    参考下图,可以看到,实例instance是由构造函数SubType创建的,默认情况下,instance的__proto__属性指向SubType.prototype(instance.constructor === SubType)。但是,由于做了SubType.prototype = new SuperType()操作,导致SubType.prototype指针指向SuperType的一个实例,并且SuperType实例的__proto__属性指向SuperType.prototype

    由此,生成原型链。

    prototype.png

    这时根据用instanceof做类型检测,结果如下:

    instance instanceof SubType === true
    instance instanceof SuperType === true
    
    小贴士
    
    如果把上面原型链继承的例子稍微做个改动,调整两行代码的顺序,如下:
    SubType.prototype.getSubValue = function    () {
      return this.subproperty;
    };
    SubType.prototype = new SuperType();
    
    var instance = new SubType();
    console.log(instance.getSubValue) // undefined
    
    答案是undefined!原因是,SubType.prototype指针指向新的对象,导致无法访问之前老对象上的方法。
    

    小结

    • typeof用于基本数据类型的类型判断,无法甄别对象具体类型(除了function);
    • instanceof用于对象的类型判断,基于原型链上的继承关系;

    (感谢@文兴的发现,文章于2017-3-6日被更正)

    微信公众号:

    相关文章

      网友评论

      • 文兴:var A = function(){}
        var B = function(){}
        B.prototype = new A()
        var b = new B()
        console.log(b.constructor === B) // false
        console.log(b.constructor === A) // true
        console.log(b instanceof B) // true

        instanceof应该不是简单通过constructor属性判断
        娜姐聊前端:@文兴 实际项目中确实用不到,只不过,从编程习惯上,建议让对象的constructor指向其构造函数。看过一些文章,不少人认为constructor其实没有什么用处,只是JavaScript语言设计的历史遗留物而已。于是,默默的呵呵呵呵了
        文兴:@娜姐_前端 所以,我至今搞不懂constructor属性是用来干什么的,他的值对和否好像都没有影响,继承和原型链都能正常工作。
        娜姐聊前端:非常感谢!!!我之前的理解有误,文章已对此做了更正。

      本文标题:[JavaScript]typeof和instanceof的区别

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