深度解析javaScript常见数据类型检查校验

前端APP 投稿 54600 1 评论

深度解析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; // false

console.log(new String("abc" instanceof String; // true

console.log(num instanceof Number; // false

console.log(new Number(123 instanceof Number; // true

console.log(boo instanceof Boolean; // false

console.log(new Boolean(true instanceof Boolean; // false

console.log(undef instanceof undefined;
// Uncaught TypeError: Right-hand side of 'instanceof' is not an object

console.log(testNull instanceof null;
// Uncaught TypeError: Right-hand side of 'instanceof' is not an object

console.log(symb instanceof Symbol; // false 
// Symbol不是构造函数,没有new操作符

console.log(bigInt instanceof BigInt; // false

console.log(Object(BigInt("22" instanceof Object; // true

console.log(Object(BigInt("22" instanceof BigInt; // true

console.log(arr instanceof Array; // true

console.log(arr instanceof Object; // true

console.log(func instanceof Function; // true

console.log(func instanceof Object; // true

console.log(obj instanceof Object; // true

console.log(obj instanceof Function; // false

console.log(null instanceof Object; // false

console.log(date1 instanceof Object; // true

console.log(setObj1 instanceof Object; //  true

console.log(setObj2 instanceof Object; //  true

console.log(mapObj instanceof Object; //  true

console.log(setObj1 instanceof Array; //  false

console.log(setObj2 instanceof Array; //  false

console.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; // String

console.log(num.constructor; // Number

console.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; // Symbol

console.log(bigInt.constructor; // BigInt

console.log(arr.constructor; // Array

console.log(func.constructor; // Function

console.log(obj.constructor; // Object

console.log(date1.constructor; // Date

console.log(constructorFn.constructor; // Function

console.log(con1.constructor; // constructorFn

console.log(setObj1.constructor; // Set

console.log(setObj2.constructor; // Set

console.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公共方法当中,作为开发中进行使用。

  • 更多用法等待补充。

源码地址

  • 码云 https://gitee.com/lewyon/vue-note
  • githup https://github.com/akari16/vue-note

深度解析javaScript常见数据类型检查校验

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

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

编程笔记 » 深度解析javaScript常见数据类型检查校验

赞同 (55) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(1)个小伙伴在吐槽
  1. 学习能力真是了不起。
    忧郁精灵 2023-09-14 04:30 (1年前) 回复