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+’]ECMAScript,’;
表明式左边的值永远是'[object
undefined]’,由此传出任何项目,此表明式都不创造,从而再次来到false.

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

           Javascript权威指南(第六版)

           Javascript设计格局与开发执行

源于为知笔记(Wiz)