JavaScript中准确的判断数据类型
在 ECMAScript 规范中,共定义了 7 种数据类型,分为基本类型和引用类型两大类。
其中:
基本类型:String、Number、Boolean、Symbol、Undefined、Null
引用类型:Object
基本类型也称为简单类型,由于其占据空间固定,是简单的数据段,为了便于提升变量查询速度,将其存储在栈(stack)中,即按值访问。
引用类型也称为复杂类型,由于其值的大小会改变,所以不能将其存放在栈中,否则会降低变量查询速度,因此,其值存储在堆(heap)中,而存储在变量处的值,是一个指针,指向存储对象的内存处,即按址访问。引用类型除 Object 外,还包括 Function 、Array、RegExp、Date 等等。
下面介绍常用的4种判断数据类型的方法,并对各个方法存在的问题进行简单的分析。
一、typeof
typeof 是一个操作符,其右侧跟一个一元表达式,并返回这个表达式的数据类型。
返回的结果用该类型的字符串(全小写字母)形式表示,包括以下 7 种:string、number、boolean、symbol、undefined、object、function 等。
typeof 'a'; // string 有效
typeof 1; // number 有效
typeof true; //boolean 有效
typeof Symbol(); // symbol 有效
typeof undefined; //undefined 有效
typeof new Function(); // function 有效
typeof null; //object 无效
typeof [1] ; //object 无效
typeof new RegExp(); //object 无效
typeof new Date(); //object 无效
总结:
- 对于基本类型,除 null 以外,均可以返回正确的结果。
- 对于引用类型,除 function 以外,一律返回 object 类型。
- 对于 null ,返回 object 类型。
- 对于 function 返回 function 类型。
其中,null 有属于自己的数据类型 Null ,引用类型中的数组、日期、正则 也都有属于自己的具体类型,而 typeof 对于这些类型的处理,只返回了处于其原型链最顶端的 Object 类型。
二、instanceof
instanceof 检测的是原型,表达式为:A instanceof B,如果 A 是 B 的实例,则返回 true,否则返回 false。
[] instanceof Array; // true
new Date() instanceof Date;// true function Person(){};
new Person() instanceof Person;//true [] instanceof Object; // true
new Date() instanceof Object;// true
new Person instanceof Object;// true
虽然 instanceof 能够判断出 [ ] 是Array的实例,但它认为 [ ] 也是Object的实例,为什么呢?
从 instanceof 能够判断出 [ ].__proto__ 指向 Array.prototype,而 Array.prototype.__proto__ 又指向了Object.prototype,最终 Object.prototype.__proto__ 指向了null,标志着原型链的结束。因此,[ ]、Array、Object 就在内部形成了一条原型链,如下图所示:

从原型链可以看出,[] 的 __proto__ 直接指向Array.prototype,间接指向 Object.prototype,所以按照 instanceof 的判断规则,[] 就是Object的实例。依次类推,类似的 new Date()、new Person() 也会形成一条对应的原型链 。
因此,instanceof 只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型。
针对数组的这个问题,ES5 提供了 Array.isArray() 方法 。该方法用以确认某个对象本身是否为 Array 类型,而不区分该对象在哪个环境中创建。
if (Array.isArray(value)){
//对数组执行某些操作
}
Array.isArray() 本质上检测的是对象的 [[Class]] 值。
[[Class]] 是对象的一个内部属性,里面包含了对象的类型信息,其格式为 [object Xxx],Xxx 就是对应的具体类型 。对于数组而言,[[Class]] 的值就是 [object Array] 。
三、constructor
当一个函数 F被定义时,JS引擎会为F添加 prototype 原型,然后再在 prototype上添加一个 constructor 属性,并让其指向 F 的引用。如下图所示:

当执行 var f = new F() 时,F 被当成了构造函数,f 是F的实例对象,此时 F 原型上的 constructor 传递到了 f 上,因此 f.constructor == F

可以看出,F 利用原型对象上的 constructor 引用了自身,当 F 作为构造函数来创建对象时,原型上的 constructor 就被遗传到了新创建的对象上, 从原型链角度讲,构造函数 F 就是新对象的类型。这样做的意义是,让新对象在诞生以后,就具有可追溯的数据类型。
同样,JavaScript 中的内置对象在内部构建时也是这样做的,如下图所示。

总结:
1. null 和 undefined 是无效的对象,因此是不会有 constructor 存在的,这两种类型的数据需要通过其他方式来判断。
2. 函数的 constructor 是不稳定的,这个主要体现在自定义对象上,当开发者重写 prototype 后,原有的 constructor 引用会丢失,constructor 会默认为 Object。
四、toString
toString() 是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]] 。这是一个内部属性,其格式为 [object Xxx] ,其中 Xxx 就是对象的类型。
对于 Object 对象,直接调用 toString() 就能返回 [object Object] 。而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。
语法:Object.prototype.toString.call(value);
Object.prototype.toString.call('') ; // [object String]
Object.prototype.toString.call(1) ; // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
Object.prototype.toString.call(Symbol()); //[object Symbol]
Object.prototype.toString.call(undefined) ; // [object Undefined]
Object.prototype.toString.call(null) ; // [object Null]
Object.prototype.toString.call(new Function()) ; // [object Function]
Object.prototype.toString.call(new Date()) ; // [object Date]
Object.prototype.toString.call([]) ; // [object Array]
Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
Object.prototype.toString.call(new Error()) ; // [object Error]
Object.prototype.toString.call(document) ; // [object HTMLDocument]
Object.prototype.toString.call(window) ; //[object global] window 是全局对象 global 的引用
JavaScript中准确的判断数据类型的更多相关文章
- javascript中的真假值、数据类型判断以及+的特殊用法
一.javascript中的假值 jQuery中拥有一组数量奇大的假值,包括 0,NaN(非数),''(空字符串),false,null,undefined 这些值在if判断中全部等于假,但这些值彼此 ...
- 在JavaScript中,如何判断数组是数组?
如果你没有注意过这个问题,那么这个标题应该会让你感到困惑,判断数据类型这么基础的问题能有什么坑呢? 少年,你不能太天真了,我们朝夕面对的这门语言,可是JavaScript呀,任何你觉得已经习以为常的东 ...
- JavaScript中instanceof的判断依据
读jquery源码的时候,发现作者为了让创建jquery对象更容易使用了用函数返回对象的方法 jQuery = function( selector, context ) { return new j ...
- 使用 JavaScript 中的变量、数据类型和运算符,计算出两个 number 类型的变量与一个 string 类型的变量的和,根据 string 类型处于运算符的不同位置得到不同的结果
查看本章节 查看作业目录 需求说明: 使用 JavaScript 中的变量.数据类型和运算符,计算出两个 number 类型的变量与一个 string 类型的变量的和,根据 string 类型处于运算 ...
- Javascript中数组的判断方法
摘要: 1.数组检测的方法: 1) typeof . 2) instanceof . 3) constructor . 4) Object.prototype.toString. 5) Array.i ...
- Javascript中的五种数据类型
Undefined 未定义.只有一个值undefined Null 只有一个值,null Boolean 在javascript中,只要逻辑表达式不返回undefined不返回null ...
- javascript中6种基本数据类型详解
javascript中有5中数据类型(也称为基本数据类型):Undefined.Null.Boolean.Number和String,还有一种复杂数据类型——object,object本质是由一组键值 ...
- javascript中的分支判断与循环
分支判断与循环 分支结构 单一选择结构(if) 二路选择结构(if/else) 内联三元运算符 ?: 多路选择结构(switch) var condition = true; if (conditio ...
- Javascript中类型的判断
数据类型的判断有这么几种方式 1.一元运算符 typeOf 2.关系运算符 instanceof 3.constructor 属性 4.prototype属性 一.typeof typeof的返回值有 ...
随机推荐
- Java——类
[类]
- Laya 首日红点逻辑
Laya 首日红点逻辑 @author ixenos 2019-08-26 10:50:27 1.原理:显然,首日红点意味着包含进程销毁的情况,那么就要持久化存储信息,这里我们使用LocalStora ...
- 【CF1247E】Rock Is Push(DP,二分)
题意:有一个n*m的方格,每一格可能为空也可能有石头,要从(1,1)走到(n,m),每次可以往右或往下走 每次走的时候都会将自己面前的所有石头向移动方向推一格,如果碰到了边界就推不过去 问方案数模1e ...
- Oracle Where子句
Oracle Where子句 作者:初生不惑 Oracle基础 评论:0 条 Oracle技术QQ群:175248146 在本教程中,将学习如何使用Oracle WHERE子句来指定过滤的条件返回符合 ...
- CentOS6.5/7安装配置Samba
CentOS6.5安装配置Samba 本文的场景是虚拟机运行CentOS6.,本机是Win7,现欲把CentOS上的一个文件夹共享出来,Win的机器可以读写. Samba与window连接需要使用Ne ...
- React-Native 之 GD (十六)首页筛选功能
1.首页筛选功能 GDCommunalSiftMenu.js /** * 筛选菜单 */ import React, { Component, PropTypes } from 'react'; im ...
- UITextView输入中文时限制字数
最近因为项目中输入用户简称时限制长度,被测试部多次提交问题,最终将解决方法分享给大家. 刚开始用最简单的方法,在textView的代理方法里面做处理 - (void)textViewDidChange ...
- 主流架构 : MVP
1 背景 MVC 平时开发APP时会发现,activity职责非常重.以MVC角度来看: M:model数据操作层(网络请求,耗时操作,数据存取,其他逻辑操作) V:view,指xml布局文件,其实并 ...
- npm 中的 --
-- 命令告诉cli-parser停止向下解析, --后面的内容会传给命令行作为命令行参数 文档地址: https://docs.npmjs.com/misc/config.html
- nginx坑记录
问题1: 配置解析过程使用ngx_cycle->pool申请内存保存配置,结果造成野指针. 背景:需求开发过程,有一些结构需要在配置解析阶段保存,然后可以动态修改.看原来的代码配置解析都是使用c ...