JavaScript判断数组的三种方法及跨框架检测方案
本文详细解析JavaScript中判断数组类型的三种常用方法:typeof、instanceof及constructor属性,并指出它们在跨框架场景下的局限性。重点介绍通过Object.prototype.toString调用判断数组的健壮方案,该方案能准确识别跨iframe创建的数组,被jQuery等主流库采用。
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 运算符。
instancefront运算符的使用
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 属性。
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> 根据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的一位维护者编写了以下函数,用于获取对象的类型名:
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)); // trueJavaScript闭包与类(Class)的区别及适用场景对比
2026-11-05 15:48:57
JavaScript入门要学ES6吗?let与箭头函数等新特性解析
2026-11-05 14:49:16
JavaScript 8种数据类型详解:基本类型与引用类型的区别
2026-11-05 14:25:15
怎么在JavaScript中使用async/await优化Ajax异步流程
2026-11-05 13:56:15
JavaScript replace回调函数实现动态正则替换逻辑
2026-11-05 13:52:13
