js中四大数据类型检测方式

685 阅读3分钟

typeof检测方式

typeof XXX 返回的都是字符串,字符串中包含的对应的数据类型

检测基本类型值(基本类型值)

typeof '字符串'                      // => "string"
typeof 1 | 0 | -1 | NaN | Infinity   // => 'number'
typeof true | false                  // => 'boolean'
typeof undefined                     // => 'undefined'
typeof null(特殊的,空对象指针)       // => 'object'
typeof Symbol(1)                     // => 'symbol'

检测引用类型值

function fn(){}
typeof fn                             // => 'function'
typeof {}                             // => 'object'
typeof /^$/                           // => 'object'
typeof new Date()                     // => 'object'
typeof []                             // => 'object'
typeof Math                           // => 'object'

typeof的局限性

  • typeof null => 'object',null不是对象,它是空对象指针
  • typeof []、/^$/、{}、new Date()、Math等所有的对象类型返回的都是字符串'object',所以无法基于typeof确定具体的对象类型,数组,正则,对象,时间对象等.

instanceof

instanceof检测某个实例是否属于这个类.

instanceof的用法

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

instanceof的机制:

检测机制: 是所有出现在原型链上的类,检测结果都为true

instanceof局限性

改变原型链的时候,结果就不可靠了.

  • 由于可以基于__proto__或者prototype改变原型链的动向,所以基于instanceof检测的结果就不看可靠
  • 基本类型值连对象都不是,更没有__proto__属性,虽然说也是所属类的实例,在js中可以调取原型上的方法,但是instanceof是不认的(1 instanceof number)
    • 这样instanceof是认的 (new Number(1) instanceof number)
    • (12).__ proto__ => (new Number(12)).proto
let arr = [1,2];
arr.__proto__ = null;
arr instanceof Array;       // false

constructor

constructor判断某个实例是不是当前类的实例

constructor用法

let arr = [1,2,3];
arr.constructor == Array  // true

constructor的检测机制:

判断某个实例是不是当前类的实例

  • arr的原型链指向了Array.prototype,Array.prototype天生自带一个constructor属性,指向Array本身.

constructor局限性

如果当前实例原型改变或者当前实例原型上的constructor改变,就不准确了

当前实例原型改变

let arr = [];
arr.__proto__ = null;
arr.constructor === Array       // false
arr.constructor                 // => undefined

当前实例原型上的constructor改变

let arr = [];
arr.__proto__.constructor = null;
arr.constructor === Array               // false
console.log(arr.__proto__.constructor)  // null

Object.prototype.toString.call/ ({}).toString.call

Object.prototype.toString,Object原型上的toString方法不是用来转换字符串的,而是用来返回当前类的所属信息的.

Number/String/Boolean/Symbol原型上的toString,valueof方法

  • toString 返回的是转换的字符串
  • valueof 返回的是原始值

Function/Array/RegExp/Date等原型上的toString方法

  • toString 返回的是转换后的字符串

Object原型上的toString方法

  • toString: 返回当前实例所属类的信息
  • valueOf: 返回原始值,基本类型值

检测依据和返回的格式

检测依据

Object原型上的方法返回的是当前实例所属类的信息

返回的格式=>十种结果

Object.prototype.toString.call({a:1})    // '[object Object]'
Object.prototype.toString.call([])       // '[object Array]'
Object.prototype.toString.call(12)       // '[object Number]'
Object.prototype.toString.call('2')      // '[object String]'
Object.prototype.toString.call(true)     // '[object Boolean]'
Object.prototype.toString.call(fn(){})   // '[object Function]'
Object.prototype.toString.call(/^$/)     // '[object RegExp]'
Object.prototype.toString.call(Date())   // '[object Date]'
Object.prototype.toString.call(new Error)// '[object Error]'
Object.prototype.toString.call(Symbol(1))// '[object Symbol]'

局限性

这种方法基本上没有局限性.可快速完成数据类型的检查

JQ源码中如何写的数据类型的检查

var class2Type = {};
'Object Array Number String Boolean Function RegExp Date Error Symbol'.split(' ').forEach(function(item,index){
    class2Type.["[object "+item+""]"] = item.toLowerCase();
})

function toType(obj){
    if(obj == null){
        return ''+obj
    }
    return typeof obj === 'object' || typeof obj === 'function' ? class2Type(Object.prototype.toString.call(obj)) || 'object' : typeof obj;
}