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. Neural Style学习2——环境安装

    neural-style Installation This guide will walk you through the setup for neural-style on Ubuntu. Ste ...

  2. 分布式服务框架dubbo原理解析(转)

    libaba有好几个分布式框架,主要有:进行远程调用(类似于RMI的这种远程调用)的(dubbo.hsf),jms消息服务(napoli.notify),KV数据库(tair)等.这个框架/工具/产品 ...

  3. php桥接设计模式

    <?php //桥接模式 abstract class info{ protected $send=null; public function __construct($send){ $this ...

  4. 使用U盘重装电脑操作系统

    1. 打开360软件管家,找一个软件"蚂蚁U盘启动"下载,下载好以后打开,电脑上插入U盘,我们制作一个启动U盘备用! 图片图片 按提示制作好启动盘后,保管好U盘. 找一个系统下载网 ...

  5. Java学习笔记11

    package welcome; import java.util.Scanner; /* * 代数问题:求解2x2线性方程 */ public class ComputeLinearEquation ...

  6. oracle 11g express 快速入门

    创建表空间CREATE TABLESPACE testdb LOGGING DATAFILE 'F:\oracle\app\oracle\oradata\XE\testdb.dbf' SIZE 100 ...

  7. gzip的使用

    经常会有文件过大,给文件的传输和增添了很多的麻烦,早先得知apach有个base64貌似可以用来压缩文件,但是测试没有什么效果,反而增大了文件的大小.今天了解了java自带的gzip包,如获至宝,超级 ...

  8. vtkAnimationCue、vtkCommand和vtkAVIWriter

    1. 用vtkAnimationCue自定义一个vtkCustomAnimationCue类,用来实现球体逐渐张开的过程: 2.用vtkCommand自定义衍生一个vtkCustomAnimation ...

  9. Silicon C8051F340之时钟系统

    一.背景 做个记录,以备下次快速开发. 二.正文 C8051F340有一个可编程内部高频振荡器.一个可编程内部低频振荡器.一个外部振荡器驱动电路 和一个4倍时钟乘法器.其中可编程内部高频振荡器在系统复 ...

  10. ubuntu下建立NFS共享,并用开发板挂载

    安装NFS服务 apt-get install nfs-kernel-server nfs-common apt-get install portmap 在/etc/exports里加入 /home/ ...