typeof和instanceof的区别是什么?

请添加图片描述

背景

typeofinstanceof操作符都是用来判断数据类型的,但是它们的使用场景却各不相同,其中一些细节也需要特别注意。

typeof

typeof运算符返回一个字符串,表示操作数的类型

使用方法如下:

typeof operand
typeof(operand)

operand表示要返回类型的对象或基本类型的表达式

typeof 666 // 'number'
typeof '666' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof null // 'object'
typeof [] // 'object'
typeof {} // 'object'

从上面例子可以看出,typeof可以精准的判断基本数据类型(null)除外

instanceof

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

使用方法如下:

object instanceof constructor

object 是指某个实例对象
constructor是指某个构造函数

// 定义构造函数
function C(){}
function D(){}

var o = new C();

o instanceof C; // true,因为 Object.getPrototypeOf(o) === C.prototype
o instanceof D; // false,因为 D.prototype 不在 o 的原型链上

o instanceof Object; // true,因为 Object.prototype.isPrototypeOf(o) 返回 true
C.prototype instanceof Object // true,同上

C.prototype = {};
var o2 = new C();

o2 instanceof C; // true

o instanceof C; // false,C.prototype 指向了一个空对象,这个空对象不在 o 的原型链上。

D.prototype = new C(); // 继承
var o3 = new D();
o3 instanceof D; // true
o3 instanceof C; // true 因为 C.prototype 现在在 o3 的原型链上

需要注意的是,如果表达式 obj instanceof Foo 返回 true,则并不意味着该表达式会永远返回 true,因为 Foo.prototype 属性的值有可能会改变,改变之后的值很有可能不存在于 obj 的原型链上,这时原表达式的值就会成为 false。另外一种情况下,原表达式的值也会改变,就是改变对象 obj 的原型链的情况,虽然在目前的 ES 规范中,我们只能读取对象的原型而不能改变它,但借助于非标准的 proto 伪属性,是可以实现的。比如执行 obj.proto = {} 之后,obj instanceof Foo 就会返回 false 了。(来源于MDN)

instanceof的实现原理,可以参考下面的代码:

/**
 * @description 判断对象是否属于某个构造函数
 * @prams left: 实例对象  right: 构造函数
 * @return boolean
 */
function myInstanceof(left, right) {
    let rightPrototype = right.prototype; // 获取构造函数的显式原型
    let leftProto = left.__proto__; // 获取实例对象的隐式原型
    while (true) {
        // 说明到原型链顶端,还未找到,则返回 false
        if (leftProto === null) {
            return false;
        }
        // 隐式原型与显式原型相等
        if (leftProto === rightPrototype) {
            return true;
        }
        // 获取隐式原型的隐式原型,重新赋值给 leftProto
        leftProto = leftProto.__proto__
    }
}

可以简单理解为:顺着原型链去找,直到找到相同的原型对象,返回true,否则为false

区别

typeofinstanceof 都是判断数据类型的方法,区别如下:

  • typeof会返回一个运算数的基本类型,instanceof 返回的是布尔值
  • instanceof 可以准确判断引用数据类型,但是不能正确判断原始数据类型
  • typeof虽然可以判断原始数据类型(null 除外),但是无法判断引用数据类型(function 除外)

扩展

从上面可以看出typeofinstanceof 都存在缺陷,所以如果想要完美的检测数据类型的话,推荐使用Object.prototype.toString.call()方法:

Object.prototype.toString.call({})
Object.prototype.toString.call([])
Object.prototype.toString.call(666)
Object.prototype.toString.call(true)
Object.prototype.toString.call(null)
Object.prototype.toString.call(undefined)

在这里插入图片描述
从结果可以看出Object.prototype.toString.call()方法比typeofinstanceof 都要好;就是写起来比较麻烦。

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值