前言

在JavaScript中,数据类型分为两大类,一种是基础数据类型,另一种则是复杂数据类型,又叫引用数据类型

  • 基础数据类型:数字Number 字符串String 布尔Boolean Null Undefined Symbols BigInt
  • 引用数据类型:日期Dete,对象Object,数组Array,方法Function, 正则regex,带键的集合:Maps, Sets, WeakMaps, WeakSets

基础数据类型和引用数据类型的区别,在之前深拷贝的文章中提到过,这里不做详细赘述。

传送门:javaScript中深拷贝和浅拷贝简单梳理

常见的几种数据校验方式

接下来会针对下面几种数据类型,进行校验

// 基本数据类型
let str = "abc";
let num = 123;
let boo = true;
let undef = undefined;
let testNull = null;
let symb = Symbol("user");
let bigInt = BigInt(9007199254740999);// 复杂-引用数据类型
let arr = [1, 2, 3, 4];
let func = function () {};
let obj = {};
let date1 = new Date();
let setObj1 = new Set();
let setObj2 = new Set([1, 2, 3]);
let mapObj = new Map();

typeof操作符

typeof操作符,会返回一个字符串,表示未经计算的操作数的类型

/*** typeof 操作符** 返回一个字符串,表示未经计算的操作数的类型。** */
console.log(typeof str); //  string
console.log(typeof num); //  number
console.log(typeof boo); //  boolean
console.log(typeof undef); //  undefined
console.log(typeof testNull); //  object
console.log(typeof symb); //  symbol
console.log(typeof bigInt); //  bigint
console.log(typeof Object(bigInt)); // object
console.log(typeof arr); //  object
console.log(typeof func); //  function
console.log(typeof obj); //  object
console.log(typeof date1); //  object
console.log(typeof setObj1); //  object
console.log(typeof setObj2); //  object
console.log(typeof mapObj); //  object
小结

使用typeof操作符的时候,我们可以看到一些较为特殊的情况:

  • null,数组array,set,map 返回的是对象object

instanceof

instanceof用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

/**** instanceof** 用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。** */console.log(str instanceof String); // falseconsole.log(new String("abc") instanceof String); // trueconsole.log(num instanceof Number); // falseconsole.log(new Number(123) instanceof Number); // trueconsole.log(boo instanceof Boolean); // falseconsole.log(new Boolean(true) instanceof Boolean); // falseconsole.log(undef instanceof undefined);
// Uncaught TypeError: Right-hand side of 'instanceof' is not an objectconsole.log(testNull instanceof null);
// Uncaught TypeError: Right-hand side of 'instanceof' is not an objectconsole.log(symb instanceof Symbol); // false
// Symbol不是构造函数,没有new操作符console.log(bigInt instanceof BigInt); // falseconsole.log(Object(BigInt("22")) instanceof Object); // trueconsole.log(Object(BigInt("22")) instanceof BigInt); // trueconsole.log(arr instanceof Array); // trueconsole.log(arr instanceof Object); // trueconsole.log(func instanceof Function); // trueconsole.log(func instanceof Object); // trueconsole.log(obj instanceof Object); // trueconsole.log(obj instanceof Function); // falseconsole.log(null instanceof Object); // falseconsole.log(date1 instanceof Object); // trueconsole.log(setObj1 instanceof Object); //  trueconsole.log(setObj2 instanceof Object); //  trueconsole.log(mapObj instanceof Object); //  trueconsole.log(setObj1 instanceof Array); //  falseconsole.log(setObj2 instanceof Array); //  falseconsole.log(mapObj instanceof Array); //  false

constructor


/*** constructor** 返回创建实例对象的 构造函数的引用。** 注意,此属性的值是对函数本身的引用,而不是一个包含函数名称的字符串** 构造函数.prototype.constructor()** */// 基本数据类型
let str = "abc";
let num = 123;
let boo = true;
let undef = undefined;
let testNull = null;
let symb = Symbol("user");
let bigInt = BigInt(9007199254740999);// 复杂-引用数据类型
let arr = [1, 2, 3, 4];
let func = function () {};
let obj = {};
let date1 = new Date();
function constructorFn() {this.name = "11";
}
let con1 = new constructorFn();
let setObj1 = new Set();
let setObj2 = new Set([1, 2, 3]);
let mapObj = new Map(); console.log(str.constructor); // Stringconsole.log(num.constructor); // Numberconsole.log(boo.constructor); // Boolean// console.log(testUndefined.constructor); // Cannot read property 'constructor' of undefined// console.log(testNull.constructor); // Cannot read property 'constructor' of null
console.log(symb.constructor); // Symbolconsole.log(bigInt.constructor); // BigIntconsole.log(arr.constructor); // Arrayconsole.log(func.constructor); // Functionconsole.log(obj.constructor); // Objectconsole.log(date1.constructor); // Dateconsole.log(constructorFn.constructor); // Functionconsole.log(con1.constructor); // constructorFnconsole.log(setObj1.constructor); // Setconsole.log(setObj2.constructor); // Setconsole.log(mapObj.constructor); // Map/**** 构造函数校验** */console.log(Function.constructor); // Function
console.log(Object.constructor); // Function
console.log(Array.constructor); // Function
console.log(Date.constructor); // Function

Object.prototype.toString.call && Object.prototype.toString.apply

Object.prototype.toString()

在使用Object.prototype.toString.call或者Object.prototype.toString.apply检查数据类型之前,我们先了解一下Object.prototype.toString和JavaScript中的构造函数Function的原型方法apply和call:

/*** 返回一个表示该对象的字符串** Object.prototype.toString()** 每个对象都有一个 toString() 方法,当该对象被表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。* 默认情况下,toString() 方法被每个 Object 对象继承。** 如果此方法在自定义对象中未被覆盖,toString() 返回 "[object type]",其中 type 是对象的类型。以下代码说明了这一点:** */let isObj = { name: "zhangsan" };
let isBoolean = true;
let isNumber = new Number(123);
let isString = "abc";
let isFun = new Function();
console.log(isObj.toString()); // [object Object]
console.log(isBoolean.toString()); // true
console.log(isNumber.toString()); // 123
console.log(isString.toString()); // abc
console.log(new Date().toString()); // Thu Apr 28 2022 16:37:19 GMT+0800 (中国标准时间)
console.log(isFun.toString()); // function anonymous() {}
call && apply
/**** call() 使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数,function.call(thisArg, arg1, arg2, ...)** apply() 使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数,unc.apply(thisArg, [argsArray])** */// call基本使用;
function a() {console.log(this);
}function b() {console.log(this);
}
a.call(b); //       function b() {}
b.call(a); //       function a() {}
  • call和apply最简单的例子表明了,改变了当前方法的this指向
  • 同时这两个方法的区别在于传参的方式

Object.prototype.toString结合Function.prototype.call && apply


/**** 使用 toString() 检测对象类型可以通过 toString() 来获取每个对象的类型。* 为了每个对象都能通过 Object.prototype.toString() 来检测,* 需要以 Function.prototype.call() 或者 Function.prototype.apply() 的形式来调用,传递要检查的对象作为第一个参数,称为 thisArg。** 那么 Object.prototype.toString 相当于 原生构造函数的实例化对象isNumber,传参数给Object.prototype.toString执行* 实际上相当于 toString.call(new ***);** */let str = "abc";
let num = 123;
let boo = true;
let undef = undefined;
let testNull = null;
let symb = Symbol("user");
let bigInt = BigInt(9007199254740999);// 复杂-引用数据类型
let arr = [1, 2, 3, 4];
let func = function () {};
let obj = {};
let date1 = new Date();
function testFun() {}
let newTest = new testFun();
let newFun = new Function();
let setObj1 = new Set();
let setObj2 = new Set([1, 2, 3]);
let mapObj = new Map();console.log(Object.prototype.toString.apply(new String("sss"))); // [object String]console.log(Object.prototype.toString.apply(str)); // [object String]console.log(Object.prototype.toString.call(num)); // [object Number]console.log(Object.prototype.toString.call(boo)); // [object Boolean]console.log(Object.prototype.toString.call(undef)); // [object Undefined]console.log(Object.prototype.toString.call(testNull)); // [object Null]console.log(Object.prototype.toString.call(symb)); // [object Symbol]console.log(Object.prototype.toString.call(Object(bigInt))); // [object BigInt]console.log(Object.prototype.toString.call(bigInt)); // [object BigInt]console.log(Object.prototype.toString.apply(arr)); // [object Array]console.log(Object.prototype.toString.call(func)); // [object Function]console.log(Object.prototype.toString.call(obj)); // [object Object]console.log(Object.prototype.toString.call(date1)); // [object Date]console.log(Object.prototype.toString.call(testFun)); // [object Function]console.log(Object.prototype.toString.call(newTest)); // [object Object]console.log(Object.prototype.toString.call(newFun)); // [object Function]console.log(Object.prototype.toString.call(setObj1)); // [object Set]console.log(Object.prototype.toString.call(setObj2)); // [object Set]console.log(Object.prototype.toString.call(mapObj)); // [object Map]

其他校验数据类型的方法:

判断是否是数组:
console.log(Array.isArray([1, 2])); // true
判断一个对象是否是空对象
// 判断空对象
function isEmptyObj(obj) {for (name in obj) {console.log(name);return false; // 不是空对象}return true;
}
console.log(isEmptyObj({}));  // true

总结

  • 不管是typeof操作符,还是其他的操作方法,都有各自的缺陷
  • 在日常的开发过程中,我们需要知道当前操作的是对象,还是构造函数生成的对象或者方法,才能针对当前需要判断的数据类型,采用最适合的方法
  • Object.prototype.toString.call或者Object.prototype.toString.apply应该是最完善的方法,在我们不确定是否是引用类型或者基本数据类型的时候,建议作为首选
  • 在了解这些判断数据类型的方式之前或者说存有疑问:为什么array数组在使用instanceof和typeof 校验Object的时候都成立,这时候需要去了解一下引用数据类型的具体内容
  • 以上判断数据类型的方法,可以在项目开发过程中,可以写入到utils公共方法当中,作为开发中进行使用。
  • 更多用法等待补充。

源码地址

文章个人博客地址:深度解析javaScript常见数据类型检查校验

欢迎关注公众号:程序员布欧,不定期更新一些前端入门文章

创作不易,转载请注明出处和作者。

深度解析javaScript常见数据类型检查校验相关推荐

  1. 深度解析JavaScript原型链

    深度解析JavaScript原型链 文章目录 深度解析JavaScript原型链 前言 JavaScript原型链,这里只分享我自己的见解 一.原型链是什么 二.心得 三图解 总结 前言 JavaSc ...

  2. 深度解析javascript中的浅复制和深复制

    在谈javascript的浅复制和深复制之前,我们有必要在来讨论下js的数据类型.我们都知道有Number,Boolean,String,Null,Undefined,Object五种类型.而Obje ...

  3. JavaScript重难点解析1(数据类型——var、let、const区别,类型补充,“===”、“typeof”、“instanceof”区别,Symbol数据类型)

    JavaScript重难点解析1(数据类型) var.let.const区别: 类型补充 "==="."typeof"."instanceof&quo ...

  4. 视频教程:Java常见面试题目深度解析!

    视频教程:Java常见面试题目深度解析! Java作为目前比较火的计算机语言之一,连续几年蝉联最受程序员欢迎的计算机语言榜首,因此每年新入职Java程序员也数不胜数.很多java程序员在学成之后,会面 ...

  5. html js定义一个变量的值,JavaScript的数据类型与变量的解析(附示例)

    本篇文章给大家带来的内容是关于JavaScript的数据类型与变量的解析(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 这篇文章,来聊聊 JS 中的数据类型与变量.这是在学 ...

  6. 42套JavaScript深度解析教学视频!合集

    本文首发于:风云社区SCOEE(社区旨在普惠软件.图片.音乐.视频.素材.文档等互联网资源.为大众提供多样化的服务,以及主要涵盖学术科学.电脑技术.文化人文.体育健身等领域的知识和信息,获得用户的支持 ...

  7. JavaScript常见变量和函数命名示例

    JavaScript作为前端开发从业人员必须掌握的3大基础知识中最重要的一环,也是平是接触时间最长.写得最多的.在开发过程中必然会遇到命名的问题,你会词穷.纠结.惆怅吗?本文的出现相信能够解决大部分烦 ...

  8. 【C/C++ POD 类型】深度解析C++中的POD类型:从理论基础到项目实践

    深度解析C++中的POD类型:从理论基础到项目实践 1. C++中的POD类型(Plain Old Data) 1.1 POD类型的定义和特性 Trivial类型 Standard layout类型 ...

  9. 单文件浏览器_图文并茂深度解析浏览器渲染原理,包看懂超值得收藏

    在我们面试过程中,面试官经常会问到这么一个问题,那就是从在浏览器地址栏中输入URL到页面显示,浏览器到底发生了什么?这个问题看起来是老生常谈,但是这个问题回答的好坏,确实可以很好的反映出面试者知识的广 ...

最新文章

  1. java开心消消乐代码_今晚请屏住呼吸,开心消消乐拍电影了!
  2. python quit函数作用_Python常用函数学习笔记
  3. 省呱呱典型用户和用户场景
  4. 理解CSS3中的background-size(对响应性图片等比例缩放)
  5. Java基础18(类加载、反射和动态代理)
  6. [SIR数据集实验][2]Java类数据集相应工具使用的小经验
  7. 我的第一次Pascal程序
  8. FPGA实现CAN接口(SJA1000)
  9. Steroids上的SQL Server Express Edition
  10. VMware中centos6.5 minimal 使用NAT模式联网
  11. Chrome , Firfox 对应IE fireEvent 的方法
  12. PyTorch Cookbook by Eric
  13. newifi3高恪魔改最新_12.08达达最新球球id账号呆瓜表
  14. idea 文件只读不可编辑--解决方法
  15. linux 软路由_软路由和硬路由的区别分析
  16. 非常可乐(广度搜索)
  17. java 读取配置文件的几种方法
  18. 病历管理系统V 1.0源码分享
  19. mp3外链,文件上传,QQ空间永久背景音乐,mp3连接,
  20. 鼠标设置按键功能方式(例如设置鼠标侧键为复制粘贴功能)

热门文章

  1. PS实用方法(抠出完整的头发丝)
  2. 惠普HP DeskJet Ink Advantage 2777 驱动
  3. 聚合支付平台需要哪方面的技术?主要有哪些功能结构?
  4. 【渝粤题库】广东开放大学 金融经济学 形成性考核
  5. Bazel 与 gtest:构建一个最简单的测试驱动开发环境
  6. 全国计算机等级考试-三级信息安全考试知识点(无顺序)
  7. jq 隔行变色(横、纵)
  8. 使用流报错:stream has already been operated upon or closed
  9. 阿里P5的测试开发工程师,都有哪些要求?
  10. 文本对比,文本差异并排对比显示实现