JS数据类型判断

JavaScript 中常见数据类型有Number、String、Boolean、Object、Array、Json、Function、Date、RegExp、Error、undefined、Null等十几种。ES6还有新增的数据类型有Symbol、Set、Map等。在实际应用中,我们经常需要判断数据类型,现在我归纳几种方法,希望对大家有所帮助。

typeof 判断(最常用)

typeof 是 JS 提供的一个运算符,专门用来检测一个变量的类型 。 typeof 有2种使用方式:typeof(表达式)和typeof 变量名,第一种是对表达式做运算,第二种是对变量做运算。

function doSomething() {
console.log('Hello World!');
}
console.log(typeof 1); // number
console.log(typeof 'Hello'); // string
console.log(typeof []); // object
console.log(typeof {}); // object
console.log(typeof doSomething); // function
console.log(typeof true); // boolean
console.log(typeof new Date()); // object
console.log(typeof new RegExp()); // object
console.log(typeof JSON.stringify({
name: 'zhencanhua'
})); // string
console.log(typeof null); // object
console.log(typeof undefined); // undefined
console.log(typeof (new Error('error!'))); // object console.log(typeof a); // undefined
console.log(typeof Symbol()); // symbol
console.log(typeof new Set()); // object
console.log(typeof new Map()); // object

从上面打印结果可以看出,typeof 不能区分引用型数据的类型和 null。另我们可以使用 Array.isArray(arr) 将数组类型的数据从中筛选出来。

instanceof 判断(了解)

instanceof 用来检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。 语法:object(实例对象) instanceof constructor(构造函数)。是的话返回 true,否则返回 false。所以, instanceof 运算符只能用作对象的判断。 针对 typeof 不能判断的引用型数据,我们可以使用 instanceof 运算符。

let arr1 = [1, 2, 3];
let obj1 = {
name: '小明'
};
function Persion() { }
let persion1 = new Persion();
console.log(arr1 instanceof Array); // true
console.log(arr1 instanceof Object); // true,Array 是Object的子类
console.log(obj1 instanceof Object); // true
console.log(obj1 instanceof Array); // false
console.log(Persion instanceof Function, Persion instanceof Object); // true true
console.log(null instanceof Object); // false
console.log(persion1 instanceof Persion, persion1 instanceof Function, persion1 instanceof Object); // true false true
// String对象和Date对象都属于Object类型
let str1 = 'Hello';
let str2 = new String();
let str3 = new String('你好');
let myDate = new Date();
console.log(str1 instanceof String, str1 instanceof Object); // false, false
console.log(str2 instanceof String, str2 instanceof Object); // true, true
console.log(str3 instanceof String, str3 instanceof Object); // true, true
console.log(myDate instanceof Date, myDate instanceof Object); // true, true

从上面的判断可以看出,instanceof 的使用限制很多,而且还不能很清晰方便的判断出一个实例是数组还是对象或方法。

针对上面方法的弊端,我们可以使用 Object.prototype上的原生toString()方法来检测数据的类型。

Object.prototype.toString.call() 判断(最靠谱)

Object 是 JS 提供的原生对象, Object.prototype.toString对任何变量都会返回这样一个字符串"[object class]",class 就是 JS 内置对象的构造函数的名字。 call是用来改变调用函数作用域的。

Object.prototype.toString() 在toString方法被调用时执行下面的操作步骤:

  1. 获取this对象的[[Class]]属性的值。(所以使用call来改变this的指向)

  2. 将字符串"[object ",第一步获取的值, 以及 "]"拼接成新的字符串并返回。

[[Class]]是一个内部属性,所有的对象(原生对象和宿主对象)都拥有该属性。在规范中,[[Class]]是这么定义的: 内部属性的描述, [[Class]] 是一个字符串值,表明了该对象的类型。

读了上面的说明,用 call 的关键地方就在第1步,获取的是 this 对象,不加 call 改变作用域时 this 指向的是Object.prototype。

function doSomething() {
console.log('Hello World!');
}
// 使用Object.prototype.toString.call来判断
console.log(Object.prototype.toString.call(1)); // [object Number]
console.log(Object.prototype.toString.call('Hello')); // [object String]
console.log(Object.prototype.toString.call(false)); // [object Boolean]
console.log(Object.prototype.toString.call({})); // [object Object]
console.log(Object.prototype.toString.call([1, 2, 3])); // [object Array]
console.log(Object.prototype.toString.call(new Error('error!'))); // [object Error]
console.log(Object.prototype.toString.call(new Date())); // [object Date]
console.log(Object.prototype.toString.call(new RegExp())); // [object RegExp]
console.log(Object.prototype.toString.call(doSomething)); // [object Function]
console.log(Object.prototype.toString.call(null)); // [object Null]
console.log(Object.prototype.toString.call(undefined)); // [object Undefined]
console.log(Object.prototype.toString.call(JSON.stringify({
name: 'zhencanhau'
}))); // [object String]
console.log(Object.prototype.toString.call(Math)); // [object Math]
console.log(Object.prototype.toString.call(Symbol('abc'))); // [object Symbol]
console.log(Object.prototype.toString.call(new Set())); // [object Set]
console.log(Object.prototype.toString.call(new Map())); // [object Map]

但在实际应用时我们只想获取返回的结果中数组的第二项,比如"[object Number]",我们只想要Number这段字符,那么我们可以写个函数进行过滤:

// 通过定义一个公共函数获取数据类型
function getTypeName(val) {
let str = Object.prototype.toString.call(val);
return /^\[object (.*)\]$/.exec(str)[1];
}
console.log(getTypeName(false)); // Boolean
console.log(getTypeName()); // Undefined
console.log(getTypeName(null)); // Null

上面的问题完美解决。

constructor 判断(比较常用)

每一个对象实例都可以通过 constrcutor 对象来访问它的构造函数 。JS 中内置了一些构造函数:Object、Array、Function、Date、RegExp、String等。我们可以通过数据的 constrcutor 是否与其构造函数相等来判断数据的类型。

var arr = [];
var obj = {};
var date = new Date();
var num = 110;
var str = 'Hello';
var getName = function(){};
var sym = Symbol();
var set = new Set();
var map = new Map(); arr.constructor === Array; // true
obj.constructor === Object; // true
date.constructor === Date; // true
str.constructor === String; // true
getName.constructor === Function; // true
sym.constructor === Symbol; // true
set.constructor === Set; // true
map.constructor === Map // true

但是这种方式仍然有个弊端,就是 constructor 所指向的的构造函数是可以被修改的。

function Name(name) {
this.name = name;
} function Stuent(age) {
this.age = age;
}
// 将构造函数Name的实例赋给Student的原型,Student的原型的构造函数会发生改变,将不再指向自身。
Stuent.prototype = new Name('张三');
Stuent.prototype.constructor === Name; // true
Stuent.prototype.constructor === Stuent; // false

以上就是我在项目中用到过的数据类型的判断方法,具体使用哪一种,还需要根据自己的实际需求来判断选择。

JS数据类型判断的几种方法的更多相关文章

  1. Js中数据类型判断的几种方法

    判断js中的数据类型有一下几种方法:typeof.instanceof. constructor. prototype. $.type()/jquery.type(),接下来主要比较一下这几种方法的异 ...

  2. JavaScript数据类型判断的四种方法

    码文不易啊,转载请带上本文链接呀,感谢感谢 https://www.cnblogs.com/echoyya/p/14416375.html 本文分享了JavaScript类型判断的四种方法:typeo ...

  3. ajax请求参数中含有特殊字符"#"的问题 (另附上js编码解码的几种方法)

    使用ajax向后台提交的时候 由于参数中含有#  默认会被截断 只保留#之前的字符  json格式的字符串则不会被请求到后台的action 可以使用encodeURIComponent在前台进行编码, ...

  4. js数据类型判断和数组判断

    这么基础的东西实在不应该再记录了,不过嘛,温故知新~就先从数据类型开始吧 js六大数据类型:number.string.object.Boolean.null.undefined string: 由单 ...

  5. JS实现深拷贝的几种方法

    引 如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力. 此篇文章中也会简单阐述到栈 ...

  6. js数据类型 判断

    1. js数据类型(两种数据类型) 基本数据类型:null undefined number boolean symbol string 引用数据类型: array object null: 空对象 ...

  7. JS数组去重的9种方法(包括去重NaN和复杂数组类型)

    其实网上已经有很多js数组的去重方法,但是我看了很多篇并自己通过代码验证,发现都有一些缺陷,于是在研究多篇代码之后,自己总结了9种方法,如果有哪里不对请及时纠正我哈~ 转载请表明出处 测试代码 let ...

  8. js数组去重的4种方法

    js数组去重,老生长谈,今天对其进行一番归纳,总结出来4种方法 贴入代码前 ,先对浏览器Array对象进行支持indexOf和forEach的polyfill Array.prototype.inde ...

  9. 判断元素16种方法expected_conditions

    前言 标签(空格分隔): 判断元素 经常有小伙伴问,如何判断一个元素是否存在,如何判断alert弹窗出来了,如何判断动态的元素等等一系列的判断,在selenium的expected_condition ...

随机推荐

  1. Java实现 蓝桥杯VIP 算法提高 洗牌

    算法提高 洗牌 时间限制:1.0s 内存限制:256.0MB 问题描述 小弱T在闲暇的时候会和室友打扑克,输的人就要负责洗牌.虽然小弱T不怎么会洗牌,但是他却总是输. 渐渐地小弱T发现了一个规律:只要 ...

  2. java中Dateformat类的详细使用(详解)

    DateFormat其本身是一个抽象类,SimpleDateFormat 类是DateFormat类的子类,一般情况下来讲DateFormat类很少会直接使用,而都使用SimpleDateFormat ...

  3. Spring zuul 快速入门实践 --看zuul如何进行服务转发

    zuul 作为springCloud 的全家桶组件之一,有着不可或缺的分量.它作为一个普通java API网关,自有网关的好处: 避免将内部信息暴露给外部: 统一服务端应用入口: 为微服务添加额外的安 ...

  4. MySQL 8.0二进制包安装

    1.官方下载 https://dev.mysql.com/downloads/mysql/ 这样就可以下载二进制包了 1.删除之前安装的MySQL包 [root@localhost ~]# rpm - ...

  5. Nice Jquery Validator 方法

    .validator() .validator( options ) 描述:根据参数初始化验证,验证 jQuery 选中的表单 参数:{Object} options - 可选,参考配置选项 示例: ...

  6. netty集群(一)-服务注册发现

    上篇文章介绍了如何搭建一个单机版本的netty聊天室:https://www.jianshu.com/p/f786c70eeccc. 一.需要解决什么问题: 当连接数超过单机的极限时,需要将netty ...

  7. Zookeeper——基本使用以及应用场景(手写实现分布式锁和rpc框架)

    文章目录 Zookeeper的基本使用 Zookeeper单机部署 Zookeeper集群搭建 JavaAPI的使用 Zookeeper的应用场景 分布式锁的实现 独享锁 可重入锁 实现RPC框架 基 ...

  8. vc6.0代码转vs2017相关问题

    vc6.0代码转vs2017相关问题 命令行 error D8016: “/ZI”和“/Gy-”命令行选项不兼容fatal error C1083: 无法打开包括文件: “WinSock2.h”: N ...

  9. 剑指 Offer 09. 用两个栈实现队列

    剑指 Offer 09. 用两个栈实现队列 用两个栈实现一个队列.队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的 ...

  10. Redis面试专题

    Redis面试专题 1. 什么是redis? Redis 是一个基于内存的高性能key-value数据库. (有空再补充,有理解错误或不足欢迎指正) 2. Reids的特点 Redis本质上是一个Ke ...