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. Linux 查找进程运行位置

    1.通过ps或者top命令查看运行的进程的pid ps -aux|grep php-fpm #或者 top 2. 获取进程的pid后,然后使用命令ls -l /proc/${pid},这个命令可以列出 ...

  2. Node.js process 模块常用属性和方法

    Node.js是常用的Javascript运行环境,本文和大家发分享的主要是Node.js中process 模块的常用属性和方法,希望通过本文的分享,对大家学习Node.js http://www.m ...

  3. pycloudtag 标签云

    原创,转载请标明 QQ:231469242 # -*- coding: utf-8 -*- """Python3.0 Created on Sat Nov 26 08:5 ...

  4. 关于jquery 集合对象的 each和click方法的 思考 -$(this)的认识

    1, 很重要的是: each: 是 自动遍历 集合中所有 item的, 是自动的; click: 包括其他所有的 "事件", 如mouseX事件, keyX事件等, 都不是 自动 ...

  5. jquery实现 复选框 全选

    $("#checkAll").change(function () { $(this).closest("table") .find(":checkb ...

  6. 【Unity3D】利用Shader以及更改Mesh实现2D游戏的动态阴影效果

    最近看到一个非常有趣的益智小游戏,是一个盗贼进入房子偷东西的, 其实这种游戏市面上已经很多了,吸引我的是那个类似手电筒的效果, 主角走到哪里,光就到哪里,被挡住的地方还有阴影.有点类似策略游戏里的战争 ...

  7. FindWindowEx用法

    函数原型:HWND FindWindowEx(HWND hwndParent,HWND hwndChildAfter,LPCTSTR lpszClass,LPCTSTR lpszWindow): 参数 ...

  8. MySQL 拷贝数据库表方式备份,还原后提示 table xxx '' doesn`t exist

    MySQL很强大,支持直接拷贝数据库文件快速备份,那数据库文件在哪里呢? 打开MySQL的配置文件 my.ini,找到 datadir 节点,如 datadir="D:/Program Fi ...

  9. 1.1ASP.NET Web API 2入门

    HTTP 不只是为了生成 web 页面.它也是建立公开服务和数据的 Api 的强大平台.HTTP 是简单的. 灵活的和无处不在.你能想到的几乎任何平台有 HTTP 库,因此,HTTP 服务可以达到范围 ...

  10. 7.1WebApi2的异常处理

    这篇文章描述错误和异常处理在 ASP.NET Web API. HttpResponseException 如果 Web API 控制器引发未捕获的异常,会发生什么?默认情况下,大多数异常被转译为 H ...