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

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

1.typeof操作符

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

  1. var s = "Nicholas";
  2. var b = true;
  3. var i = 22;
  4. var u;
  5. var n = null;
  6. var o = new Object();
  7. alert(typeof s); //string
  8. alert(typeof i); //number
  9. alert(typeof b); //boolean
  10. alert(typeof u); //undefined
  11. alert(typeof n); //object
  12. alert(typeof o); //object

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

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

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

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

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

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

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

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

  1. function isArray(object) {
  2. return object!= null && typeof object == "object" && 'splice' in object && 'join' in object;
  3. }
  4. var liar = { splice: 1, join: 2 };
  5. 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];
  2. alert(Object.prototype.toString.call(arr)); //"[object Array]"
由于原生数组的构造函数名与全局作用域无关,因此使用 toString() 就能保证返回一致的值。利用这一点,可以创建如下函数用来检测变量是否是数组类型:
  1. function isArray(value){
  2. return Object.prototype.toString.call(value) == "[object Array]";
  3. }
同样,也可以基于这一思路来测试某个值是不是原生函数或正则表达式
  1. function isFunction(value){
  2. return Object.prototype.toString.call(value) == "[object Function]";
  3. }
  4. function isRegExp(value){
  5. return Object.prototype.toString.call(value) == "[object RegExp]";
  6. }
Object.prototpye.toString() 本身也可能会被修改。这里讨论的技巧假设 Object.prototpye.toString() 是未被修改过的原生版本。
(2016-4-26续)
我们发现,这些函数的大部分实现都是相同的,不同的只是Object.prototype.toString.call(value)返回的字符串。为了避免多余的代码,可以尝试把这些字符串作为参数提前植入isType函数,代码如下:
  1. var isType=function(type) {
  2. return function (obj) {
  3. return Object.prototype.toString.call(obj)=='[object '+type+']';
  4. }
  5. };
  6. var isString=isType('String');
  7. var isArray=isType('Array');
  8. var isNumber=isType('Number');
  9. var isRegExp=isType('RegExp');
  10. console.log(isNumber(2));
我们还可以用循环语句,来批量注册这些isType函数
  1. var Type={};
  2. for (var i = 0,type;type=['String','Array','Number'][i++];){
  3. (function (type) {
  4. Type['is'+type]=function (obj) {
  5. return Object.prototype.toString.call(obj)=='[object '+type+']';
  6. }
  7. })(type)
  8. }
  9. //调用检测函数
  10. Type.isArray([]);//输出:true
  11. Type.isString("str");//输出:true
注意上述代码使用闭包封闭了变量type;这样当函数检测函数调用时从内到外查找变量type,会先找到封闭在闭包环境的type.试想一下不使用闭包来完成上述批量注册函数:
  1. var Type={};
  2. for (var i = 0,type;type=['String','Array','Number'][i++];){
  3. Type['is'+type]=function (obj) {
  4. return Object.prototype.toString.call(obj)=='[object '+type+']';
  5. }
  6. }
  7. console.log(Type.isArray([]));//输出false
  8. console.log(Type.hasOwnProperty("isArray"));//输出:true
  9. 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. icon图标

     http://images2015.cnblogs.com/blog/575577/201609/575577-20160901194344636-1596119396.png  http://im ...

  2. <<< sqlserver、Mysql、Oracle数据库优缺点

    sqlserver 优点: 易用性.适合分布式组织的可伸缩性.用于决策支持的数据仓库功能.与许多其他服务器软件紧密关联的集成性.良好的性价比等:   为数据管理与分析带来了灵活性,允许单位在快速变化的 ...

  3. JS-抽奖系统-实现原理

    有本事中奖的,过来找我换红包!!哈哈!! <meta charset="UTF-8"> <title>抽奖系统</title> <styl ...

  4. R语言读取本地文件注意事项

    R里面应该用/,而不是\ ,或者用两个\\   R区分大小写,所以应该用C:,而不是c:

  5. 11月6日下午PHP注册审核(审核状态控制登录、可以更改审核状态)

    1.创建登录界面 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://ww ...

  6. Java数据结构——带权图

    带权图的最小生成树--Prim算法和Kruskal算法 带权图的最短路径算法--Dijkstra算法 package graph; // path.java // demonstrates short ...

  7. 面试题目——《CC150》数学与概率

    面试题7.2:三角形的三个顶点上各有一只蚂蚁.如果蚂蚁开始沿着三角形的边爬行,两只或三只蚂蚁撞到一起的概率有多大?假定每只蚂蚁会随机选一个方向,每个方向被选到的几率相等,而且三只蚂蚁的爬行速度相同. ...

  8. CSS知识回顾--读《CSS 那些事儿》笔记

    由于之前有了解过CSS的相关知识,有了一定的基础,所以读起<CSS 那些事儿>不是很有难度,况且我现在读起来时,CSS3和HTML5比较流行,这里只是记录一些CSS知识记录,不做详细铺开, ...

  9. C语言基础(6)-char类型

    1. char常量.变量 使用单引号‘’引起来的就是char的常量 ‘a’是一个char类型的常量 “a”是一个字符串类型的常量 1是一个int型的常量 ‘1’是一个char型的常量 char a; ...

  10. @SuppressWarnings注解的用法

    一.前言 编码时我们总会发现如下变量未被使用的警告提示: 上述代码编译通过且可以运行,但每行前面的"感叹号"就严重阻碍了我们判断该行是否设置的断点了.这时我们可以在方法前添加 @S ...