深度解析javaScript常见数据类型检查校验
前言
在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常见数据类型检查校验相关推荐
- 深度解析JavaScript原型链
深度解析JavaScript原型链 文章目录 深度解析JavaScript原型链 前言 JavaScript原型链,这里只分享我自己的见解 一.原型链是什么 二.心得 三图解 总结 前言 JavaSc ...
- 深度解析javascript中的浅复制和深复制
在谈javascript的浅复制和深复制之前,我们有必要在来讨论下js的数据类型.我们都知道有Number,Boolean,String,Null,Undefined,Object五种类型.而Obje ...
- JavaScript重难点解析1(数据类型——var、let、const区别,类型补充,“===”、“typeof”、“instanceof”区别,Symbol数据类型)
JavaScript重难点解析1(数据类型) var.let.const区别: 类型补充 "==="."typeof"."instanceof&quo ...
- 视频教程:Java常见面试题目深度解析!
视频教程:Java常见面试题目深度解析! Java作为目前比较火的计算机语言之一,连续几年蝉联最受程序员欢迎的计算机语言榜首,因此每年新入职Java程序员也数不胜数.很多java程序员在学成之后,会面 ...
- html js定义一个变量的值,JavaScript的数据类型与变量的解析(附示例)
本篇文章给大家带来的内容是关于JavaScript的数据类型与变量的解析(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 这篇文章,来聊聊 JS 中的数据类型与变量.这是在学 ...
- 42套JavaScript深度解析教学视频!合集
本文首发于:风云社区SCOEE(社区旨在普惠软件.图片.音乐.视频.素材.文档等互联网资源.为大众提供多样化的服务,以及主要涵盖学术科学.电脑技术.文化人文.体育健身等领域的知识和信息,获得用户的支持 ...
- JavaScript常见变量和函数命名示例
JavaScript作为前端开发从业人员必须掌握的3大基础知识中最重要的一环,也是平是接触时间最长.写得最多的.在开发过程中必然会遇到命名的问题,你会词穷.纠结.惆怅吗?本文的出现相信能够解决大部分烦 ...
- 【C/C++ POD 类型】深度解析C++中的POD类型:从理论基础到项目实践
深度解析C++中的POD类型:从理论基础到项目实践 1. C++中的POD类型(Plain Old Data) 1.1 POD类型的定义和特性 Trivial类型 Standard layout类型 ...
- 单文件浏览器_图文并茂深度解析浏览器渲染原理,包看懂超值得收藏
在我们面试过程中,面试官经常会问到这么一个问题,那就是从在浏览器地址栏中输入URL到页面显示,浏览器到底发生了什么?这个问题看起来是老生常谈,但是这个问题回答的好坏,确实可以很好的反映出面试者知识的广 ...
最新文章
- java开心消消乐代码_今晚请屏住呼吸,开心消消乐拍电影了!
- python quit函数作用_Python常用函数学习笔记
- 省呱呱典型用户和用户场景
- 理解CSS3中的background-size(对响应性图片等比例缩放)
- Java基础18(类加载、反射和动态代理)
- [SIR数据集实验][2]Java类数据集相应工具使用的小经验
- 我的第一次Pascal程序
- FPGA实现CAN接口(SJA1000)
- Steroids上的SQL Server Express Edition
- VMware中centos6.5 minimal 使用NAT模式联网
- Chrome , Firfox 对应IE fireEvent 的方法
- PyTorch Cookbook by Eric
- newifi3高恪魔改最新_12.08达达最新球球id账号呆瓜表
- idea 文件只读不可编辑--解决方法
- linux 软路由_软路由和硬路由的区别分析
- 非常可乐(广度搜索)
- java 读取配置文件的几种方法
- 病历管理系统V 1.0源码分享
- mp3外链,文件上传,QQ空间永久背景音乐,mp3连接,
- 鼠标设置按键功能方式(例如设置鼠标侧键为复制粘贴功能)