JavaScript判断数组类型的三种方法及跨框架解决方案

作者:青柠时间:2026-10-25 10:56:09浏览:602

本文详解JavaScript中判断数组类型的三种常用方法:typeof、instanceof以及Object.prototype.toString。重点分析了前两种方法在跨iframe场景下的局限性,并推荐了基于Object.prototype.toString.call的健壮检测方案,该方案能准确识别各类内置对象类型,被jQuery等主流框架广泛采用。

1) typeof 运算符

typeof运算符的局限性

typeof是一个一元运算符,其返回值是描述操作数类型的字符串。可能的返回值包括:"number"、"string"、"boolean"、"object"、"function"以及"undefined"(后者常用于检测变量是否存在)。


然而,typeof的功能存在局限,对于Date和RegExp等特定类型,它同样返回"object"。例如:


代码如下:

 
typeof {}; // "object"
typeof []; // "object"
typeof new Date(); // "object"

因此,typeof仅在区分对象与原始类型时有效。若要区分不同类型的对象,必须借助其他方法,例如instanceof运算符或对象的constructor属性。



2)instanceof 运算符。

instanceof与constructor属性检测

instancefront运算符要求左侧操作数为对象,右侧为类名或构造函数。若左侧对象是右侧类或构造函数的实例,则返回true;若非实例或为null,则返回false。示例如下:



[] instanceof Array; // true


[] instanceof Object; // true


[] instanceof RegExp; // false


new Date instanceof Date; // true



基于此,可以使用instanceof运算符来判断对象是否为数组类型:



function isArray(arr)


{

return arr instanceof Array;


}

3)constructor 属性。

在JavaScript中,每个对象都拥有constructor属性,该属性引用了初始化该对象的构造函数,常用于判断未知对象的类型。若通过typeof确定某值为对象,即可利用constructor属性进一步判断其具体类型。因此,判断数组的函数也可编写为:



function isArray(arr)


{

return typeof arr == "object" && arr.constructor == Array;


}

在多数情况下,使用instanceof运算符或constructor属性足以检测对象是否为数组,许多JavaScript框架也采用这两种方式。


但在跨框架(cross-frame)页面中,上述检测方法会失效。原因在于不同iframe中创建的数组不会共享其prototype属性。例如:


代码如下:

 
<script>
window.onload=function(){
var iframe_arr=new window.frames[0].Array;
alert(iframe_arr instanceof Array); // false
alert(iframe_arr.constructor == Array); // false
} 
</script>
<body>
<iframe></iframe>
</body>

基于Object.prototype.toString的健壮检测方案

据Ajaxian介绍,一种精确的检测方法是跨原型链调用toString()方法,即Object.prototype.toString(),这能解决上述跨框架问题。



当执行Object.prototype.toString(o)时,会遵循以下步骤:


1)获取对象o的[[Class]]属性。


2)拼接字符串:"[object "+结果(1)+"]"。


3)返回结果(2)。



例如:



Object.prototype.toString.call([]); // 返回 "[object Array]"


Object.prototype.toString.call(/reg/ig); // 返回 "[object RegExp]"



据此,我们可以编写一个健壮的判断对象是否为数组的函数:


代码如下:

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

该方法得到了多位国外JavaScript专家的认可,并将在即将发布的jQuery 1.3版本中用于数组检测。



prototype.js的一位维护者编写了以下函数,用于获取对象的类型名:


代码如下:

 
/** 
* Returns internal [[Class]] property of an object
* 
* Ecma-262, 15.2.4.2
* Object.prototype.toString( )
* 
* When the toString method is called, the following steps are taken:
* 1. Get the [[Class]] property of this object.
* 2. Compute a string value by concatenating the three strings "[object ", Result (1), and "]".
* 3. Return Result (2).
* 
* __getClass(5); // => "Number"
* __getClass({}); // => "Object"
* __getClass(/foo/); // => "RegExp"
* __getClass(''); // => "String"
* __getClass(true); // => "Boolean"
* __getClass([]); // => "Array"
* __getClass(undefined); // => "Window"
* __getClass(Element); // => "Constructor"
* 
*/ 
function __getClass(object)
{ 
return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
}; 

进一步扩展,可用于检测各种对象类型:


代码如下:

 
var is =
{ 
types : ["Array", "Boolean", "Date", "Number", "Object", "RegExp", "String", "Window", "HTMLDocument"]
} 
for(var i = 0, c; c = is.types[i ++ ]; )
{ 
is[c] = (function(type)
{ 
return function(obj)
{ 
return Object.prototype.toString.call(obj) == "[object " + type + "]";
} 
} 
})(c);
} 
alert(is.Array([])); // true
alert(is.Date(new Date)); // true
alert(is.RegExp(/reg/ig)); // true
作者最新文章