typeof与instancof在进行类型判断时的区别

typeof与instancof在进行类型判断时的区别

如果熟悉JavaScript的程序员应该对这两个判断函数不陌生,但是这两个在本质上还是有一定的区别。

typeof的实现原理

typeof其实最被广大程序员们使用,typeof可以用来判断number,string,undefined,null,boolean,object,symbol这七种数据类型。在typeof进行对基本数据类型的判断时,它能准确的告诉我们属于哪种数据类型。
关于typeof的实现原理,其实在JavaScript底层存储变量的时候,会在变量的机器码的低位1~3位存储其类型信息

  • 000:对象
  • 010:浮点数
  • 100:字符串
  • 110:布尔
  • 1:整数
    null:所有机器码均为0
    undefined:用 −2^30 整数来表示
    所以,typeof 在判断 null 的时候就出现问题了,由于 null 的所有机器码均为0,因此直接被当做了对象来看待。

instanceof的实现原理

关于instanceof可以自己手动实现一个,它主要是通过原型链一直找到这个需要判断的对象的原型,直到找到为止就返回true,否则就返回false。
以下是我自己实现的instanceof:

// 手动实现一个instanceof
        function myInstanceof(obj,type) {
            // 如果是基本数据类型就返回false
            if (typeof obj !== 'object' || obj === null) {
                return false
            }
            
            // getPrototypeOf是object对象自带的函数,可以获取到参数的原型对象
            let proto = Object.getPrototypeOf(obj)
            while (true) {
                // 如果查找到底部还没有找到相应的原型对象,则返回false
                if (proto == null) {
                    return false
                }
                if (proto == type.prototype) {
                    // 找到相同的原型对象后
                    return true
                }
            }
        }

但是对于instanceof和typeof的使用场景,当如果是基本数据类型就使用typeof进行判断,如果是对一个对象需要判断它的数据类型就需要使用instanof,例如数组和除 Function 外的所有构造函数的类型都是 ‘object’
例如:

var str = new String('String');
var num = new Number(100);

typeof str; // 返回 'object'
typeof num; // 返回 'object'

var func = new Function();

typeof func; // 返回 'function'

这种时候就可以使用instanceof来判断这个对象为什么类型。
以下是typeof使用时返回值的全列,拷贝自MDN:

// 数值
typeof 37 === 'number';
typeof 3.14 === 'number';
typeof(42) === 'number';
typeof Math.LN2 === 'number';
typeof Infinity === 'number';
typeof NaN === 'number'; // 尽管它是 "Not-A-Number" (非数值) 的缩写
typeof Number(1) === 'number'; // Number 会尝试把参数解析成数值

typeof 42n === 'bigint';

// 字符串
typeof '' === 'string';
typeof 'bla' === 'string';
typeof `template literal` === 'string';
typeof '1' === 'string'; // 注意内容为数字的字符串仍是字符串
typeof (typeof 1) === 'string'; // typeof 总是返回一个字符串
typeof String(1) === 'string'; // String 将任意值转换为字符串,比 toString 更安全

// 布尔值
typeof true === 'boolean';
typeof false === 'boolean';
typeof Boolean(1) === 'boolean'; // Boolean() 会基于参数是真值还是虚值进行转换
typeof !!(1) === 'boolean'; // 两次调用 ! (逻辑非) 操作符相当于 Boolean()


// Symbols
typeof Symbol() === 'symbol';
typeof Symbol('foo') === 'symbol';
typeof Symbol.iterator === 'symbol';


// Undefined
typeof undefined === 'undefined';
typeof declaredButUndefinedVariable === 'undefined';
typeof undeclaredVariable === 'undefined';


// 对象
typeof {a: 1} === 'object';

// 使用 Array.isArray 或者 Object.prototype.toString.call
// 区分数组和普通对象
typeof [1, 2, 4] === 'object';

typeof new Date() === 'object';
typeof /regex/ === 'object'; // 历史结果请参阅正则表达式部分


// 下面的例子令人迷惑,非常危险,没有用处。避免使用它们。
typeof new Boolean(true) === 'object';
typeof new Number(1) === 'object';
typeof new String('abc') === 'object';

// 函数
typeof function() {} === 'function';
typeof class C {} === 'function'
typeof Math.sin === 'function';
  • 值得注意的是即使对NaN进行判断,依然返回的是一个Number。
  • 对正则表达式进行判断返回的是一个对象。
  • 对一个数组进行判断返回的是一个对象

第三种判断数据类型的方法

还有一个不错的判断类型的方法,就是Object.prototype.toString,我们可以利用这个方法来对一个变量的类型来进行比较准确的判断,在MDN上有这么一句话:Early JS environments return ‘[object Object]’ for null, so it’s best to directly check for it.后面接的就是前面对象的数据类型。

Object.prototype.toString.call(1) // "[object Number]"

Object.prototype.toString.call('hi') // "[object String]"

Object.prototype.toString.call({a:'hi'}) // "[object Object]"

Object.prototype.toString.call([1,'a']) // "[object Array]"

Object.prototype.toString.call(true) // "[object Boolean]"

Object.prototype.toString.call(() => {}) // "[object Function]"

Object.prototype.toString.call(null) // "[object Null]"

Object.prototype.toString.call(undefined) // "[object Undefined]"

Object.prototype.toString.call(Symbol(1)) // "[object Symbol]"

总结

当需要对一个对象进行具体数据类型判断的时候就可以使用instanceof,但是instanceof的判断是不准确的,可以使用typeof来判断基本数据类型,不过要注意判断null类型的问题。如果想要获取准确的判断对象实例的数据类型,可以采用Object.prototype.toString.call 方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值