24.js的数据类型

56 阅读4分钟

在js中,我们通常将数据内存中的存储方式不同。 将他们分为2种数据类型.

简单数据类型(基本数据类型)

  • Number:数字
  • String:字符串
  • Boolean:布尔
  • Null:表示缺少对象(一般用来指完全为空的对象)
  • Undefined:申明了变量但是未赋值
  • Symbol:独一无二的值(ES6新增,解决命名冲突的问题)
  • BigInt:任意大的整数(没有2^53-1范围限制)  基本数据类型是直接存储在栈中的简单数据段,占据空间小,属于被频繁使用的数据。拷贝的时候的时候可以直接拷贝数据

复杂数据类型(引用数据类型)

  引用数据类型是存储在堆内存中,占据空间大。引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址,当解释器寻找引用值时,会检索其在栈中的地址,取得地址后从堆中获得实体.浅拷贝的话是拷贝内存地址的指针.

  • Object:普通对象
  • Function/function:构造函数/函数
  • Array:数组
  • Reg:正则
  • Date:时间
  • Math:数学

数据类型判断

在日常开发中 我们经常会使用到数据类型的判断,以下几种都是我们常用的几种方法

typeof

  • typeof 是一个操作符,其右侧跟一个一元表达式,并返回这个表达式的数据类型。
  • typeof判断基础数据类型(不包含bull)没问题,但是判断复杂数据类型的时候会有一些意外的结果,除了function返回function,其他都是返回object.
  • typeof的原理是检查数据的二进制,而null的是000开头的和对象是一样的所以null返回的也是object

instanceof

  • instanceof 是用来判断 A 是否为 B 的实例,表达式为:A instanceof B,如果 A 是 B 的实例,则返回 true,否则返回 false。
  • instanceof 不能判断简单数据类型 除非这个数据不是字面量,而是通过new出来的 比如
a = new String('a')
a instanceof String // true
  • instanceof判断复杂数据类型的时候,也有一些问题,比如
[] instanceof Array // true
[] instanceof Object // true

复杂数据类型除了他自己的构造函数还可以是Object

constructor

  • 通过原型链的constructor可以指回构造函数的原理
  • null 和 undefined 是无效的对象,因此是不会有 constructor 存在的,这两种类型的数据需要通过其他方式来判断
  • 函数的 constructor 是不稳定的,这个主要体现在自定义对象上,当开发者重写 prototype 后,原有的 constructor 引用会丢失,constructor 会默认为 Object

toString

  • toString() 是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]] 。这是一个内部属性,其格式为 [object Xxx] ,其中 Xxx 就是对象的类型。

  • 对于 Object 对象,直接调用 toString()  就能返回 [object Object] 。而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。

一些特殊的判断

  • Array.isArray() 判断参数是否是数据
  • isNaN()判断参数是不是非数字

toType

这是一个jQuery封装的判断数据类型的,十分好用,可以写到项目的通用函数里面直接调用

      var getProto = Object.getPrototypeOf; //获取实例的原型对象
      var class2type = {};
      var toString = class2type.toString; //Object.prototype.toString 检测数据类型
      var hasOwn = class2type.hasOwnProperty; //Object.prototype.hasOwnProperty
      var fnToString = hasOwn.toString; //Function.prototype.toString 把函数转换字符串
      var ObjectFunctionString = fnToString.call(Object); //"function Object() { [native code] }"
      // 循环数据中的每一项:建立数据类型检测的映射表
      //  + [object Boolean]/[object Number]/[object String]都是为了处理基于”构造函数“创建的基本数据值的引用类型值,最后期许检测出来的结果依然是"boolean"/"number"/"string"
      //  typeof new Number(10) -> "object"
      //  toString.call(new Number(10)) -> "[object Number]"
      [
        'Boolean',
        'Number',
        'String',
        'Symbol',
        'Function',
        'Array',
        'Date',
        'RegExp',
        'Object',
        'Error',
        'GeneratorFunction'
      ].forEach(function (name) {
        class2type['[object ' + name + ']'] = name.toLowerCase();
      });

      // 检测数据类型的公共方法
      function toType(obj) {
        // null/undefined
        if (obj == null) {
          return obj + '';
        }
        // 如果是引用数据类型(包含:new Number(10)这种),则基于Object.prototype.toString来检测(拿检测的结果到之前建立的映射表中去匹配查找,找到对象的小写数据类型);而基本数据类型,之前排除了null/undefined,剩下的基于typeof即可解决!
        return typeof obj === 'object' || typeof obj === 'function'
          ? class2type[toString.call(obj)] || 'object'
          : typeof obj;
      }