• JS数据类型及判断&typeof和instanceof的区别


    数据类型

    JS 数据类型分为两大类:

    1、原始数据类型StringNumberBooleanUndefinedNullSymbol(es6 新增,表示独一无二的值)、Bigint(es10 新增)

    2、引用类型Object

    其中 Object 中又包含了很多子类型(通过原型链继承),比如 ArrayDateFunctionMathMapSetRegexp 等等,总之除了原始数据类型皆为引用类型。

    存储方式

    原始数据类型:直接存储在栈(stack)中,占据空间小、大小固定,属于被频繁使用数据

    引用数据类型:同时存储在栈(stack)和堆(heap)中,占据空间大、大小不固定。引用数据类型在栈中存储指针,指向堆中存的实体的地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。

    ps:这样设计的原因在于
    原始类型因为占据空间是固定的,可以将他们存在较小的内存中-栈中,这样便于迅速查询变量的值。引用数据类型大小不固定且会变化,固然不能直接放在栈中,但是其地址是固定的,可以将地址存在栈中。

    类型判断

    类型判断有以下几种方式

    • typeof
    • instanceof
    • constructor
    • Object.prototype.toString.call()

    typeof

    原始类型中除了null会判断成Object,其它类型都可以通过 typeof 来判断
    引用类型除了函数 都会显示 Object

    console.log(typeof 1); // number
    console.log(typeof true); // boolean
    console.log(typeof "hello"); // string
    console.log(typeof undefined); // undefined
    console.log(typeof null); // 被 typeof 解释为 object
    console.log(typeof {}); // object
    console.log(typeof function () {}); // function
    console.log(typeof []); // object 数组被解释为 object
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    instanceof

    能正确判断引用类型,不能精准判断原始数据类型
    原理:通过递归查找原型链的方式来判断是否为构造函数的实例

    console.log({} instanceof Object); // true
    console.log(function () {} instanceof Function); // true
    console.log(1 instanceof Number); // false
    console.log(true instanceof Boolean); // false
    console.log("hello" instanceof String); // false
    console.log(Array.isArray([])); // true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    constructor

    通过判断 constructor 确定数据类型,不可靠在于,如果创建的对象更改了原型,就不准确了。

    console.log((1).constructor === Number); // true
    console.log(true.constructor === Boolean); // true
    console.log("str".constructor === String); // true
    console.log([].constructor === Array); // true
    console.log(function () {}.constructor === Function); // true
    console.log({}.constructor === Object); // true
    
    // 看个错误的例子
    function Fn () {}
    
    Fn.prototype = [];
    
    const f = new Fn();
    
    console.log(f.constructor === Fn); // false
    console.log(f.constructor === Array); // true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    Object.prototype.toString.call()

    前几种方式或多或少都存在一些缺陷,Object.prototype.toString.call() 综合来看是最佳选择,能判断的类型最完整也最准确。

    const oproto = Object.prototype;
    const serialize = Object.prototype.toString;
    
    console.log(serialize.call(1)); // [object Number]
    console.log(serialize.call(true)); // [object Boolean]
    console.log(serialize.call("hello")); // [object String]
    console.log(serialize.call([])); // [object Array]
    console.log(serialize.call({})); // [object Object]
    console.log(serialize.call(() => {})); // [object Function]
    console.log(serialize.call(null)); // [object Null]
    console.log(serialize.call(undefined)); // [object Undefined]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    例如判断一个对象是否为函数只需要使用if (serialize.call(fn) === '[object Function])'即可

    其他

    其余的还有es6引入的新的Array方法Array.isArray可以直接判断数组类型

    综上

    • typeof可以判断基础数据类型,但是遇到null会误判为object,不能用于判断引用数据类型
    • instanceof可以用于检测引用数据类型,原理是根据原型链查找是否为构造函数的实例,不能用于判断基础数据类型
    • constructor直接根据构造函数进行判断类型,但是如果手动更改过对象的prototype,则不准确
    • Object.prototype.toString.call() 方法最好最通用
  • 相关阅读:
    C语言函数指针简介
    数据库备份与恢复
    【车辆分类】基于matlab的视频中车辆跟踪监测分类算法仿真,包括背景差分与帧间差分以及形态学处理
    spark性能调优 | 内存优化
    小白入门:什么是CURD?
    Flutter关于StatefulWidget中State刷新时机的一点实用理解
    如何防范各类联属欺诈?
    python openai playground使用教程
    Linux安装及管理应用程序
    zipkin2.24.2源码install遇见的问题
  • 原文地址:https://blog.csdn.net/MAINKEYS/article/details/136715529