ECMAScriptJavascript数据类型检测

Javascript有5种简单数据类型和同等栽复杂数据类

  • 主导数据类:String,Boolean,Number,Undefined, Null
  • 援数据类型:Object(Array,Date,RegExp,Function)

1.typeof操作符

倘若检测一个变量是勿是基本数据类, typeof 操作符是极品的工具。

var s = "Nicholas";var b = true;var i = 22;var u;var n = null;var o = new Object();alert(typeof s); //stringalert(typeof i); //numberalert(typeof b); //booleanalert(typeof u); //undefinedalert(typeof n); //objectalert(typeof o); //object

唯独由上面的推行结果好视,如果变量的价是一个靶要 null,则 typeof
操作符会像例子中所展示之那样返回”object”
那问题来了,如何检测Null呢?
如果想将null和对象分别开,则须进行展示检查

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

2.instanceof 操作符

虽然在检测中心数据列时 typeof
是特别能干的帮手,但每当检测引用类型的价经常,这个操作符的用不甚。 通常,
我们连无是眷恋清楚某值是目标,而是想了解她是啊品种的目标。为夫,
ECMAScript提供了 instanceof 操作符,其语法如下所示:

result = variable instanceof constructor

若变量是加引用类型(根据它的原型链来识别)的实例,那么instanceof 操作符就会见返回 true。请看下的例证:

alert(person instanceof Object); // 变量 person 是 Object 吗?alert(colors instanceof Array); // 变量 colors 是 Array 吗?alert(pattern instanceof RegExp); // 变量 pattern 是 RegExp 吗?

不仅如此,对于自定义之靶子,此方式仍然有效,请看下面的例子。

function Animal() {}function Bird() {}Bird.prototype = new Animal();Bird.prototype.fly = function () {//do some thingalert('I can fly!');}var pigeon = new Bird();alert(pigeon instanceof Bird); //true 毫无疑问alert(pigeon instanceof Animal); //true 由于原型链的关系alert(pigeon instanceof Object); //true 

 根据规定,所有援类型的价都是
Object
的实例。因此,在检测一个援类型值和
Object
构造函数时,
instanceof
操作符始终会回来 true。当然,如果利用 instanceof 操作符检测中心类型的价,则该操作符始终会回到 false,因为基本类型不是目标。看似instanceof
操作符能完全缓解检测对象类型的题材,实际行使中也确实够用底。然而instanceof仍然在一个题目**,它一旦只有一个大局执行环境。因检测对象是不是为数组类型为条例, **如果网页中含多个框架,那其实就存在个别只以上不同之全局执行环境,从而有个别个以上不同版本的
Array 构造函数。如果您自一个框架为外一个框架传入一个再三组,那么传入的数组与于次只框架中原生创建的数组分别持有各自不同之构造函数。

var iframe = document.createElement('iframe');    document.body.appendChild(iframe);    xArray = window.frames[window.frames.length-1].Array;       var arr = new Array("1","2","3","4","5");   alert(arr instanceof Array); // false

由每个iframe都生同样效自己之行环境,跨frame实例化的靶子彼此是无联合享原型链的,因此致上述检测代码失效!为了缓解者题材,
ECMAScript 5 新增了 Array.isArray()
方法。这个法子的目的是终极确定有值到底是匪是数组,而无其是以谁全局执行环境遭受创造的。我们循以地方的例证说明

var iframe = document.createElement('iframe');    document.body.appendChild(iframe);    xArray = window.frames[window.frames.length-1].Array;       var arr = new xArray("1","2","3","4","5");   alert(arr instanceof Array); // falsealert(Array.isArray(arr));//true

说及数组类型,下面总结一下哪判定变量是否为数组类型?

  • 方法一

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

function isArray(object) {       return object!= null && typeof object == "object" && 'splice' in object && 'join' in object;       }  var liar = { splice: 1, join: 2 };   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]]
属性,这个特性被不怕指定了上述字符串中之构造函数名。举个例子吧。

var arr=[1,2,3,4];alert(Object.prototype.toString.call(arr)); //"[object Array]"

出于原生数组的构造函数名与大局作用域无关,因此使用 toString()
就可知管返回一致的价。利用这或多或少,可以创造如下函数用来检测变量是否是数组类型:

function isArray(value){return Object.prototype.toString.call(value) == "[object Array]";}

一如既往,也得根据这等同思路来测试某只价是匪是原生函数或正则表达式

function isFunction(value){return Object.prototype.toString.call(value) == "[object Function]";}function isRegExp(value){return Object.prototype.toString.call(value) == "[object RegExp]";}

Object.prototpye.toString() 本身吗说不定会见受修改。这里讨论的技术假设
Object.prototpye.toString() 是不被改过之原生版本。

(2016-4-26续)

咱俩发现,这些函数的大部分落实都是一致的,不同之仅是Object.prototype.toString.call(value)返回的字符串。为了避免多余的代码,可以品尝把这些字符串作为参数提前植入isType函数,代码如下:

var isType=function(type) {    return function (obj) {      return Object.prototype.toString.call(obj)=='[object '+type+']';    }};var isString=isType('String');var isArray=isType('Array');var isNumber=isType('Number');var isRegExp=isType('RegExp');console.log(isNumber(2));

咱俩尚可用循环语句,来批量注册这些isType函数

var Type={};for (var i = 0,type;type=['String','Array','Number'][i++];){    (function (type) {        Type['is'+type]=function (obj) {         return Object.prototype.toString.call(obj)=='[object '+type+']';        }    })(type)}//调用检测函数Type.isArray([]);//输出:trueType.isString("str");//输出:true

只顾上述代码应用闭包封闭了变量type;这样当函数检测函数调用时由内及外查找变量type,会先找到封闭在闭包环境的type.试想转手非采取闭包来形成上述批量登记函数:

var Type={};for (var i = 0,type;type=['String','Array','Number'][i++];){       Type['is'+type]=function (obj) {         return Object.prototype.toString.call(obj)=='[object '+type+']';        }    }console.log(Type.isArray([]));//输出falseconsole.log(Type.hasOwnProperty("isArray"));//输出:trueconsole.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设计模式与开支执行

根源为理解笔记(Wiz)