js 数据类型检测,几种方法我知道大致区别了

484 阅读7分钟

这是我参与8月更文挑战的第11天,活动详情查看:8月更文挑战

前言

检测数据类型再开发中也是比较常用的, 其实想到检测数据类型可能大脑里面就是instanceoftypeofObject.property.toString.call()。 以上三种检测数据类型,今天就一块测试下具体有什么区别? 或者是不是还有什么其他的方法?

开始

开始测试

instanceof

instanceof 其实只能检测出引用数据类型:ArrayObjectFunction......

代码测试:

//示例1(数字类型Number):
console.log( 123 instanceof Number, 'instanceof检测数字类型')
//输出:false "instanceof检测数字类型"。
//**结论: instanceof 不能用来检测数字类型**



//示例2(字符串String)
console.log('' instanceof String, 'instanceof检测字符串类型')
//输出:false "instanceof检测字符串类型"
//**结论:instanceof 不能用来检测字符串类型**


//示例3(布尔Boolean)
console.log(true instanceof Boolean, 'instanceof检测布尔类型')
// 输出: false "instanceof检测布尔类型"
//**结论: instanceof 不能用来检测布尔类型**


//示例4(null)
let a;
console.log(a instanceof null, 'instanceof检测Null类型')
//抛出错误:Uncaught TypeError: Right-hand side of 'instanceof' is not an object
//**结论: instanceof 不能用来检测null类型**



//示例5(undefined)
console.log(undefined instanceof undefined, 'instanceof检测undefined类型')
//抛出错误:VM120801:1 Uncaught TypeError: Right-hand side of 'instanceof' is not an object
//**结论:instanceof不能检测undefined类型**



//示例6(Function)
console.log((() => {}) instanceof Function, 'instanceof检测函数类型')
//输出: true "instanceof检测函数类型"
//**结论:instanceof能检测函数类型**


//示例7(Object)
console.log({} instanceof Object, 'instanceof检测Object类型')
//输出: true "instanceof检测Object类型"
//**结论:instanceof能检测Object类型**


//示例8(Array)
console.log([] instanceof Array, 'instanceof检测Array类型')
//输出: true "instanceof检测Array类型"
//**结论:instanceof能检测Array类型**


//示例8(Date)
console.log((new Date()) instanceof Date, 'instanceof检测Date类型')
//输出: true "instanceof检测Date类型"
//**结论:instanceof能检测Date类型**


// 示例9(new String())
console.log((new String(123)) instanceof String, 'instanceof检测通过new出来的String类型')
//输出: true "instanceof检测通过new出来的String类型"
//**结论:instanceof能检测通过new出来的String类型**

示例9的输出截图:

大家有兴趣可以去研究下 Stringnew String() 的区别,求其实是没用到这个new String()

结论: instanceof 能对ArrayObjectFunctionDate等进行检测,其他(引用类型)都不支持;

instanceof 原理

[] instanceof Array为例, instanceof的工作原理就是调用[]的每一层__proto__隐士原型Arrayprototype显示原型 做对比

代码实现示例:

function instance_of(L, R) {//L 表示左表达式,R 表示右表达式 
   const O = R.prototype;   // 取 R 的显示原型 
   L = L.__proto__;  // 取 L 的隐式原型
    while (true) {    
      if (L === null) {
         return false;   
      }

      if (O === L) {
        return true;   
      }
      L = L.__proto__;  
    }
}

//测试一下:
console.log(instance_of([], Array), '数组类型检测')
console.log(instance_of({}, Object), '对象类型检测')
console.log(instance_of(()=>{}, Function), '函数类型检测')
/**
* true "数组类型检测"
* true "对象类型检测"
* true "函数类型检测"
*/

typeof

typeof支持检测基本类型:NumberStringUndefinedBoolean, 支持检测引用类型;Function, 无法检测ObjectArrayDateNull

代码测试:

  //示例1:typeof 检测数字类型
  console.log(typeof(123) === 'number') 
  //输出:true   
  //结论:typeof支持检测数字类型




 //示例2: typeof 检测字符串类型
  console.log(typeof('') === 'string') 
  //输出:true   
  //结论:typeof支持检测字符串类型



   //示例3: typeof 检测布尔类型
   console.log(typeof(true) === 'boolean') 
  //输出:true   
  //结论:typeof支持检测布尔类型


  //示例4: typeof 检测null类型
  console.log(typeof(null) === 'null') 
  //输出:false , 打印出来是:"object"   
  //结论:typeof支持检测null类型


  //示例5: typeof 检测undefined类型
  console.log(typeof(undefined) === 'undefined') 
  //输出:true  
  //结论:typeof支持检测undefined类型



  //示例6: typeof 检测数组类型
  console.log(typeof([]) === 'array') 
  //输出:false,   打印:"object"
  //结论:typeof不支持检测数组类型


  //示例7: typeof 检测对象类型
  console.log(typeof({}) === 'object') 
  //输出:true,  虽然是true,但是它检测数组也是object,所以用来检测对象是不太准确的
  //结论:typeof不支持检测对象类型


  //示例8: typeof 检测函数
  console.log(typeof(() => {}) === 'function') 
  //输出:true
  //结论:typeof支持检测对象类型

结论:typeof支持检测(Number, String, Boolean, Undefined, Function)

typeof原理

typeof原理:不同的对象在底层都表示为二进制,在Javascript中二进制前(低)三位存储其类型信息。

// 000: 对象
// 010: 浮点数
// 100:字符串
// 110:布尔
// 1:整数

typeof null 为"object", 原因是因为 不同的对象在底层都表示为二进制,在Javascript中二进制前(低)三位都为0的话会被判断为Object类型,null的二进制表示全为0,自然前三位也是0,所以执行typeof时会返回"object"。一个不恰当的例子,假设所有的Javascript对象都是16位的,也就是有16个0或1组成的序列,猜想如下:

Array: 1000100010001000
null:  0000000000000000

typeof []  // "object"
typeof null // "object"

因为Array和null的前三位都是000。为什么Array的前三位不是100?因为二进制中的“前”一般代表低位, 比如二进制00000011对应十进制数是3,它的前三位是011

Object.property.toString.call()

Object.property.toString.call()能检测所有的数据类型 代码测试

  let Type = {}
  const type = ['String', 'Array', 'Number', 'Function', 'Boolean', 'Object', 'Undefined', 'Null']

  for( let i = 0; i < type.length; i++) {
      (function(type){
        Type[`is${type}`] = function(obj) {
            return Object.prototype.toString.call(obj) === `[object ${type}]`
        }
      })(type[i])
  }

console.log(Type.isArray([]), '数组类型检测')
console.log(Type.isString(''), '字符串类型检测')
console.log(Type.isNumber(123), '数值类型检测')
console.log(Type.isFunction(() => {}),'函数类型检测')
console.log(Type.isBoolean(true), '布尔类型检测')
console.log(Type.isObject({}) , '对象类型检测')
console.log(Type.isUndefined(undefined) , 'undefined类型检测')
console.log(Type.isNull(null) , 'null类型检测')


/**
 * 输出:
 * 
 * true "数组类型检测"
 * true "字符串类型检测"
 * true "数值类型检测"
 * true "函数类型检测"
 * true "布尔类型检测"
 * true "对象类型检测"
 * true "undefined类型检测"
 * true "null类型检测"
 * **/

其他

Array.isArray()

Array.isArray()可以用来检测是否是数组

用法示例:

console.log(Array.isArray([]), '检测是否是数组') //输出: true "检测是否是数组"

Array.isArray 原理

if (!Array.isArray) {
  Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}

//对 就上面的Object.prototype.toString.call()

isNaN()

isNaN() 用来判断是否是数字类型? 是数字返回false, 不是数字返回true

  • 1、'123'这种类型纯数字的字符串也会返回false,
  • 2、''空字符串也会返回false
  • 3、null也会返回false
  • 4、布尔类型也会返回false 用法示例:
console.log(isNaN(123), '用来检测是否是数字类型') 
//输出:false "用来检测是否是数字类型"

console.log(isNaN(''), '用来检测是否是数字类型') 
//输出:false "用来检测是否是数字类型"

console.log(isNaN(null), '用来检测是否是数字类型') 
//输出:false "用来检测是否是数字类型"

console.log(isNaN(true), '用来检测是否是数字类型') 
//输出:false "用来检测是否是数字类型"

isNaN 原理解析

isNaN函数接受一个参数,原理是先尝试将参数转换为数值型,调用的是Number()方法,再进行判断


//1. 数值:自然转为数值
//2. 字符串
Number('123') // 123
Number('123abc') // NaN
Number(' ') // 0

// 3. 布尔值
Number(true) // 1
Number(false) // 0

// 4. undefined
Number(undefined) // NaN

//5. null
Number(null) // 0

总结:根据isNaN()方法返回的是true还是false可以检测参数是否可以像number那样是可运算的,如果是不可运算的,则可赋予这个参数一个默认的值或者是其他合适的内容,就可以得到一个隐式转换参数数值的函数。我一直以为是判断是否是数值类型.......

constructor

利用constructor 进行类型检测, 缺点:一个数据的constructor是可以被更改的, 且基本数据类型没有constructor无法检测

代码示例:

console.log([].constructor === Array, 'constructor检测数据类型')
//输出: true "constructor检测数据类型"

console.log({}.constructor === Object, 'constructor检测数据类型')
//输出: true "constructor检测数据类型"

console.log((() => {}).constructor === Function, 'constructor检测数据类型')
//输出: true "constructor检测数据类型"

总结

检测数据类型大致就以上几种instanceoftypeofObject.property.toString.call()、Array.isArray()、constructor、isNaN(),大家如果还有其他方式校验数据类型,记得评论分享吖

参考链接

结束语

  • 大家好 我是三原,多谢您的观看,我会更加努力(๑•̀ㅂ•́)و✧多多总结。
  • 每个方法都是敲出来验证过通过的,有需要可以放心复制。
  • 如果您给帮点个赞👍就更好了 谢谢您~~~~~
  • 期待您的关注