你了解JS数据类型检测吗?

339 阅读3分钟

前言

大家工作中必定会经常会对类型做判断,从而实现一些逻辑处理,那咱们就话不多说,今天带领大家来搞一下这个类型检测

本文需要知识点

  • 原型链

  • 数据类型种类

检测数据类型

tyepof 

instanceof

constructor

Object.prototype.toString.call()

typeof篇

我给大家分了一些类 可以稍微看下,----------大家看完就会发现 null 数组 正则都是 Object;

typeof 12; typeof NaN  // number

typeof "" // string

typeof true  // boolean

typeof undefined // undefined

typeof function () { }; // function

typeof null; typeof {}; typeof []; typeof /^$/ // Object Why???

这个经过大量的查询,发现 typeof会在计算机底层基于二进制来进行检测, 而且对象都是以 000 开头的, 所以检测出来也是 Object

instanceof 篇

很多经典面试题,就会问你 instanceof 和 typeof 区别 大家可以看到typeof arr 即是 数组 又是对象 why?

let arr = [];
arr instanceof Array  // true
arr instanceof RegExp  // false
arr instanceof Object // true


function fn() {

}

fn.prototype = Array.prototype;
let f = new fn;
console.log(f,f instanceof Array) // true

fn instanceof Array  // true
fn instanceof Object  // true

let num = 1;
num instanceof Number

铁铁,你可以打开他的原型链瞅一眼,你会发现 他是根据 只要出现在原型链上面,他就是true;
当你 取检测基本数据类型的时候,你就会发现他都是false,也就是不支持基本数据类型检测;
最重要的一点,可以自由修改原型

如何实现 instanceof

// 如果实现一个 instanceof 呢?

function instance_of(current, target) {
    let targetPrototype = target.prototype;
    let proto = Object.getPrototypeOf(current) // 兼容IE 取原型
    while (true) {
        if (proto === null) return false;
        if (proto === targetPrototype) return true;
        proto = Object.getPrototypeOf(proto);
    }
}

constructor 篇

一些人可能对这个方法有些陌生,他的原型上面会有一个constructor的,会标志他是属于什么类型的, 在一般情况下(无外力介入)还是比较准的,给大家准备了些小例子

let arr = [];
let num = 1;
// Number.prototype.constructor = '哦豁豁哦豁豁';
// Numbrr.constructor === Number // false
brr.constructor === Number // true

arr.constructor === Array // true
arr.constructor === RegExp // false
arr.constructor === Object // false

Object.prototype.toString() 篇

这个标准的辨别类型的方法,但是有个缺点,麻烦,这老多字母

// 当定义个对象,然后调用原型上的 toString方法时,
// 因为此时 toString方法 指向调用它的
let obj = {
    name: '彭于晏'
};
obj.toString()  //  "[object,Object]"

// 咱们猜一把: 既然Object.prototype.toString会返回object,通过call来改变this是他不指向Object,
//而是调用者的时候, 就会发现,没有一个重复的,哇哈哈哈,标准

如何实现一个toType方法呢?

结合他们的优缺点实现

function toType(obj) {
    if (obj == null) { // 注意 不是绝对等于
        return obj;
    }
    return typeof obj === "object" || typeof obj === 'function' ? Object.prototype.toString(obj) || "object" : typeof obj;
}

总结

  • typeof 适合检测基本数据类型 当然函数也行,对象差点意思
    直接在计算机底层 基于数据类型的值(二进制)进行检测
    typeof null;
    why? 因为typeof 在底层检测的时候,对象都是以 000 开头的, null 也是 所以检测出来就是对象

  • instanceof 检测当前实例是否属于这个类 准确性不好
    底层: 当前类只要出现在实例原型链上 都是 true
    js对原型指向问题,支持度比较高,所以会导致instanceof 检测不准
    而且不支持检测基本数据类型

  • constructor
    无外力介入的情况下还是比较准的,而且基本类型也支持。(无外力介入:不人为去修改)

  • Object.prototype.toString.call()
    标准检测数据类型 Object.prototype.toString 返回当前实例所属;