Javascript有5种简单数据类型和一种复杂数据类型

  • 基本数据类型:String,Boolean,Number,Undefined, Null
  • 引用数据类型:Object(Array,Date,RegExp,Function)

1.typeof操作符

要检测一个变量是不是基本数据类型, typeof 操作符是最佳的工具。

    1. var s = "Nicholas";
    1. var b = true;
    1. var i = 22;
    1. var u;
    1. var n = null;
    1. var o = new Object();
    1. alert(typeof s); //string
    1. alert(typeof i); //number
    1. alert(typeof b); //boolean
    1. alert(typeof u); //undefined
    1. alert(typeof n); //object
    1. alert(typeof o); //object

但是从上面的执行结果可以看到,如果变量的值是一个对象或 null,则 typeof 操作符会像例子中所示的那样返回"object" ,那么问题来了,如何检测Null呢? 如果想将null和对象区分开,则必须进行显示检查

    1. function getType(obj) {
    1. return (obj === null) ? "null" : typeof (obj);
    1. }

2.instanceof 操作符
虽然在检测基本数据类型时 typeof 是非常得力的助手,但在检测引用类型的值时,这个操作符的用处不大。 通常, 我们并不是想知道某个值是对象,而是想知道它是什么类型的对象。为此, ECMAScript提供了 instanceof 操作符,其语法如下所示:
    1. result = variable instanceof constructor

如果变量是给定引用类型(根据它的原型链来识别)的实例,那么instanceof 操作符就会返回 true。请看下面的例子:

    1. alert(person instanceof Object); // 变量 person 是 Object 吗?
    1. alert(colors instanceof Array); // 变量 colors 是 Array 吗?
    1. alert(pattern instanceof RegExp); // 变量 pattern 是 RegExp 吗?
不仅如此,对于自定义的对象,此方法仍然有效,请看下面的例子。
    1. function Animal() {
    1. }
    1. function Bird() {
    1. }
    1. Bird.prototype = new Animal();
    1. Bird.prototype.fly = function () {
    1. //do some thing
    1. alert('I can fly!');
    1. }
    1. var pigeon = new Bird();
    1. alert(pigeon instanceof Bird); //true 毫无疑问
    1. alert(pigeon instanceof Animal); //true 由于原型链的关系
    1. alert(pigeon instanceof Object); //true

 根据规定,所有引用类型的值都是 Object 的实例。因此,在检测一个引用类型值和 Object 构造函数时, instanceof 操作符始终会返回 true。当然,如果使用 instanceof 操作符检测基本类型的值,则该操作符始终会返回 false,因为基本类型不是对象。看似instanceof 操作符能完全解决检测对象类型的问题,实际应用中也确实够用的。但是instanceof仍然存在一个问题,它假定只有一个全局执行环境。以检测对象是否为数组类型为例, 如果网页中包含多个框架,那实际上就存在两个以上不同的全局执行环境,从而存在两个以上不同版本的 Array 构造函数。如果你从一个框架向另一个框架传入一个数组,那么传入的数组与在第二个框架中原生创建的数组分别具有各自不同的构造函数。
    1. var iframe = document.createElement('iframe');
    1. document.body.appendChild(iframe);
    1. xArray = window.frames[window.frames.length-1].Array;
    1. var arr = new Array("1","2","3","4","5");
    1. alert(arr instanceof Array); // false
由于每个iframe都有一套自己的执行环境,跨frame实例化的对象彼此是不共享原型链的,因此导致上述检测代码失效!为了解决这个问题, ECMAScript 5 新增了 Array.isArray() 方法。这个方法的目的是最终确定某个值到底是不是数组,而不管它是在哪个全局执行环境中创建的。我们仍以上面的例子说明
    1. var iframe = document.createElement('iframe');
    1. document.body.appendChild(iframe);
    1. xArray = window.frames[window.frames.length-1].Array;
    1. var arr = new xArray("1","2","3","4","5");
    1. alert(arr instanceof Array); // false
    1. alert(Array.isArray(arr));//true

说到数组类型,下面总结一下如何判断变量是否为数组类型?
  • 方法一

判断其是否具有“数组性质”,如slice()方法。但是存在自己给该变量定义slice方法的情况,故有时会失效

    1. function isArray(object) {
    1. return object!= null && typeof object == "object" && 'splice' in object && 'join' in object;
    1. }
    1. var liar = { splice: 1, join: 2 };
    1. alert(isArray(liar));//true,成功骗过了检测方法

  • 方法二

obj instanceof Array这个方法在前面已经介绍过了,也是不完美的。

  • 方法三

使用上文所述新方法Array.isArray(),但是支持 Array.isArray() 方法的浏览器有 IE9+、 Firefox 4+、 Safari 5+、 Opera 10.5+和 Chrome。对于版本比较旧的浏览器此方法不被支持。

  • 方法四

以上那些方法看上去无懈可击,但是终究会有些问题,接下来介绍的方法可以说是无懈可击了。

大家知道,在任何值上调用 Object 原生的 toString() 方法,都会返回一个[object NativeConstructorName] 格式的字符串。每个类在内部都有一个[[Class]] 属性,这个属性中就指定了上述字符串中的构造函数名。举个例子吧。
    1. var arr=[1,2,3,4];
    1. alert(Object.prototype.toString.call(arr)); //"[object Array]"
由于原生数组的构造函数名与全局作用域无关,因此使用 toString() 就能保证返回一致的值。利用这一点,可以创建如下函数用来检测变量是否是数组类型:
    1. function isArray(value){
    1. return Object.prototype.toString.call(value) == "[object Array]";
    1. }
同样,也可以基于这一思路来测试某个值是不是原生函数或正则表达式
    1. function isFunction(value){
    1. return Object.prototype.toString.call(value) == "[object Function]";
    1. }
    1. function isRegExp(value){
    1. return Object.prototype.toString.call(value) == "[object RegExp]";
    1. }
Object.prototpye.toString() 本身也可能会被修改。这里讨论的技巧假设 Object.prototpye.toString() 是未被修改过的原生版本。
(2016-4-26续)
我们发现,这些函数的大部分实现都是相同的,不同的只是Object.prototype.toString.call(value)返回的字符串。为了避免多余的代码,可以尝试把这些字符串作为参数提前植入isType函数,代码如下:
    1. var isType=function(type) {
    1. return function (obj) {
    1. return Object.prototype.toString.call(obj)=='[object '+type+']';
    1. }
    1. };
    1. var isString=isType('String');
    1. var isArray=isType('Array');
    1. var isNumber=isType('Number');
    1. var isRegExp=isType('RegExp');
    1. console.log(isNumber(2));
我们还可以用循环语句,来批量注册这些isType函数
    1. var Type={};
    1. for (var i = 0,type;type=['String','Array','Number'][i++];){
    1. (function (type) {
    1. Type['is'+type]=function (obj) {
    1. return Object.prototype.toString.call(obj)=='[object '+type+']';
    1. }
    1. })(type)
    1. }
    1. //调用检测函数
    1. Type.isArray([]);//输出:true
    1. Type.isString("str");//输出:true
注意上述代码使用闭包封闭了变量type;这样当函数检测函数调用时从内到外查找变量type,会先找到封闭在闭包环境的type.试想一下不使用闭包来完成上述批量注册函数:
    1. var Type={};
    1. for (var i = 0,type;type=['String','Array','Number'][i++];){
    1. Type['is'+type]=function (obj) {
    1. return Object.prototype.toString.call(obj)=='[object '+type+']';
    1. }
    1. }
    1. console.log(Type.isArray([]));//输出false
    1. console.log(Type.hasOwnProperty("isArray"));//输出:true
    1. console.log(type);//undefined
我们会发现类型检测函数失效了,数组类型检测函数并不能检测数组了,产生这种情况的原因是当isArray函数执行时,for循环已经执行结束了,此时type=['String','Array','Number'][3]=undefined,检测函数中的语句 Object.prototype.toString.call(obj)=='[object '+type+']'; 表达式右侧的值永远是'[object undefined]',因此传入任何类型,此表达式都不成立,从而返回false.

参考:Javascript高级程序设计(第3版)

           Javascript权威指南(第六版)
           Javascript设计模式与开发实践



Javascript数据类型检测的更多相关文章

  1. JavaScript 数据类型检测总结

    JavaScript 数据类型检测总结 原文:https://blog.csdn.net/q3254421/article/details/85483462 在js中,有四种用于检测数据类型的方式,分 ...

  2. javascript 数据类型 -- 检测

    一.前言 在上一篇博文中 Javascript 数据类型 -- 分类 中,我们梳理了 javascript 的基本类型和引用类型,并提到了一些冷知识.大概的知识框架如下: 这篇博文就讲一下在写代码的过 ...

  3. JavaScript: 数据类型检测

    由于JavaScript是门松散类型语言,定义变量时没有类型标识信息,并且在运行期可以动态更改其类型,所以一个变量的类型在运行期是不可预测的,因此,数据类型检测在开发当中就成为一个必须要了解和掌握的知 ...

  4. JavaScript数据类型检测 数组(Array)检测方式

    前言 对于确定某个对象是不是数组,一直是数组的一个经典问题.本文专门将该问题择出来,介绍什么才是正确的javascript数组检测方式 typeof 首先,使用最常用的类型检测工具--typeof运算 ...

  5. JavaScript数据类型检测详解

    //JS该如何检测数据的类型呢? //使用关键字: typeof //输出结果依次为:'number','string','boolean'. console.log(typeof 17); cons ...

  6. javascript数据类型检测方法

    一.字符串.数字.布尔值.undefined的最佳选择市使用 typeof 运算符进行检测: 对于字符串,typeof 返回"string" 对于数字,typeof 返回" ...

  7. JavaScript系列文章:不能不看的数据类型检测

    由于JavaScript是门松散类型语言,定义变量时没有类型标识信息,并且在运行期可以动态更改其类型,所以一个变量的类型在运行期是不可预测的,因此,数据类型检测在开发当中就成为一个必须要了解和掌握的知 ...

  8. javascript 中检测数据类型的方法

    typeof 检测数据类型 javascript 中检测数据类型有好几种,其中最简单的一种是 typeof 方式.typeof 方法返回的结果是一个字符串.typeof 的用法如下: typeof v ...

  9. 【JavaScript框架封装】数据类型检测模块功能封装

    数据类型检测封装后的最终模块代码如下: /*数据类型检验*/ xframe.extend(xframe, { // 鸭子类型(duck typing)如果它走起路来像鸭子,叫起来也是鸭子,那么它就是鸭 ...

随机推荐

  1. 【codevs2495】 水叮当的舞步

    http://codevs.cn/problem/2495/ (题目链接) 题意 给出一个N*N的矩阵,其中元素有5种颜色,每次可以将左上角元素所在的连通块更换一种颜色,连通块指相邻并且颜色相同的元素 ...

  2. [bigdata] 使用Flume hdfs sink, hdfs文件未关闭的问题

    现象: 执行mapreduce任务时失败 通过hadoop fsck -openforwrite命令查看发现有文件没有关闭. [root@com ~]# hadoop fsck -openforwri ...

  3. HTML5魔法堂:全面理解Drag & Drop API

    一.前言    在HTML4的时代,各前端工程师为了实现拖拽功能可说是煞费苦心,初听HTML5的DnD API觉得那些痛苦的日子将一去不复返,但事实又是怎样的呢?下面我们一起来看看DnD API的真面 ...

  4. 初学Java 精简知识点总结

    面对Java丰富的知识资料,很多初学者难免觉得迷惘,该学什么,怎么去学?下面给大家讲Java基础知识做了精简总结,来帮助你梳理学习思路,赶快看看吧! 方法/步骤1 对象的初始化(1) 非静态对象的初始 ...

  5. hibernate UUID问题

    前言:hibernate对于字符串类型主键支持UUID主键生成策略,(号称是世界上唯一的字符串) 运行环境:运行环境:hibernate5.2,mysql5.6 一,使用hibernate给Strin ...

  6. linux 乱码

    xwindow终端乱码 在/etc/sysconfig/i18n文件的最后一行添加如下内容: export LC_ALL="zh_CN.GB18030" vi /etc/sysco ...

  7. 前端项目构建工具---Grunt

    什么是Grunt? grunt是javascript项目构建工具,在grunt流行之前,前端项目的构建打包大多数使用ant.(ant具体使用 可以google),但ant对于前端而言,存在不友好,执行 ...

  8. 【转载】使用Pandas进行数据匹配

    使用Pandas进行数据匹配 本文转载自:蓝鲸的网站分析笔记 原文链接:使用Pandas进行数据匹配 目录 merge()介绍 inner模式匹配 lefg模式匹配 right模式匹配 outer模式 ...

  9. ROS 5.x自动定时备份并发送到邮箱(实用)

    博主使用ROS已经有很长一段时间了,但经常会忘记备份配置与数据库,加上ROS本身自带的User-Man数据库并不是非常稳定,1年中总会出现1-2次数据丢失的情况.所以费了一定功夫才找到真正可用自动备份 ...

  10. [Linux] 账户管理命令(一)

    用户和用户组 Linux用户组的所有信息都存放在/etc/group文件中.具有某种共同特征的用户集合起来就是用户组(Group).用户组(Group)配置文件主要有 /etc/group和/etc/ ...