技术频道导航
HTML/CSS
.NET技术
IIS技术
PHP技术
Js/JQuery
Photoshop
Fireworks
服务器技术
操作系统
网站运营

赞助商

分类目录

赞助商

最新文章

搜索

详细介绍5种方法检查JavaScript对象是否数组

作者:admin    时间:2022-5-31 20:17:3    浏览:

“数组是类似列表的对象,其原型具有执行遍历和变异操作的方法。” — MDN 文档

如何在 JavaScript 中检查对象是否数组?本文将详细介绍 5 种方法,并比较它们的优缺点:

方法一:Array.isArray([])

ECMAScript 5 (ES5) 引入了 Array.isArray() 方法来检查数组,因为 typeof 无法将数组与其他对象区分开来,例如内置对象 DateRegExp

使用 Array.isArray() 也有助于确保我们的对象不为空,因为由于长期存在的错误,null 具有“对象”类型。

下面是使用 Array.isArray([]) 检查数组的示例:

 

方法二:Object.prototype.toString.call([])

冗长的 JavaScript 语句 Object.prototype.toString.call() 可以区分数组和其他类型的对象,因为它返回的字符串比 typeof 更详细地指定了对象类型。

因为此方法适用于任何对象,所以我称其为 JavaScript 中类型检查的最佳方法。这是一个例子: 

 

虽然冗长,但此方法适用于任何原始类型和任何对象。它总是返回变量的构造函数的名称。

换句话说,Object.prototype.toString.call() 有点像 instanceof 的逆向,尽管它在 iframe 中运行良好。

上述 isArray() 函数的行为应该与内置的 Array.isArray() 函数相同。

这里要注意的一点是 typeof {} 返回“object”(小写),但 Object.prototype.toString.call({}).slice(8,-1) 返回“Object”(大写)对象 {}和数组 [] 的“Array”(大写)。

与所有这些方法一样,如果尚未声明变量,此方法将不起作用。稍后我将讨论检查未声明的变量。 

方法三:[] instanceof 数组

使用关键字 instanceof 可用于检查数组或任何类型的 JavaScript 对象。

“instanceof 运算符测试构造函数的原型属性是否出现在对象原型链的任何位置。” — MDN 文档

语法很简单,如下代码示例所示: 

 

 但请注意,iframe 可能会破坏这种行为,如 Mozilla 开发人员网络文档中 Array.isArray 中所述:

instanceof vs isArray
在检查 [an] Array 实例时,Array.isArray 优于 instanceof,因为它通过 iframe 工作。— MDN 文档

这意味着我们可能根本不想使用 instanceof 来检查数组,以防万一我们的 JavaScript 代码最终在 iframe 中运行。

方法四:[].constructor

这是一个类似于 instanceof 的方法——调用 JavaScript 对象的 .constructor 属性。

.constructor 属性将返回构造函数,对于数组,它是函数 Array()(即 JavaScript 类 Array)。

访问该函数的 .name 属性将给出字符串“Array”,该字符串可用于形成对数组是否存在的简单检查。

由于 .constructor 属性返回函数 Array()(即 JavaScript 类 Array),因此也可以直接将其与全局 Array 对象(即返回的函数 Array() 所引用的对象)进行比较。

换句话说,实际上不必使用 .name 属性:[].constructor===Array 等价于 [].constructor.name==="Array"

这是一个代码示例:

 

Object.prototype.toString.call() 类似,访问 .constructor 属性将适用于任何类型的 JavaScript 值,包括原语——尽管您不能访问 .constructor 以获取未定义或空值。

(请注意,instanceof 关键字适用于对象,但不适用于基元。当然,instanceofiframe 中存在错误。)

正如我们在上面看到的,使用没有 null 检查的 .constructor 会导致 null 和 undefined 的 TypeError — 与 Array.isArray() 相比的缺点,后者只会为这两个值返回 false

并且,与到目前为止介绍的任何方法一样,如果想尝试访问未声明的变量,它们将引发 ReferenceError。 

一句警告:.constructor 是可变的

在继续之前,值得注意的是 .constructor 并不健壮,因为它是一个可以在以后覆盖的对象属性。

请记住,如果你出于任何原因通过原型覆盖您的构造函数,则 arr.constructor === Array 测试将返回 falseArray.isArray(arr) 仍然返回 true

所以只要记住一个对象的 .constructor 属性是“可变的”——它可能已经在代码中的某个地方从它的原始值改变了。

方法 5:&& 和 [].constructor(空检查!)

这是一个简洁的单行代码,它将在检查数组的同时检查非空值:[] && [].constructor === Array

nullundefined 都是false,这意味着它们在条件语句中评估为false,但所有对象都是true,包括空数组。检查 [] && [].constructor === Array 将为 null 或未定义的值返回 false,而单独的 .constructor 会引发错误。

包含逻辑 AND (&&) 运算符的优点是可以避免由于 nullundefined 没有属性而发生的 TypeError。这是有效的,因为 && 是一个“短路运算符”。通过使用逻辑 AND (&&),我们在尝试访问 .constructor 属性之前检查该值是否为true。这是一个代码示例:

 

为了提高代码的可读性,你可以考虑使用松散相等(==)来显式地检查空值:[] != null && [].constructor。使用 !=(松散相等运算符)意味着 nullundefined 彼此相等。

更明确的检查将使用严格相等:[] !== null && [] !== undefined && [].constructor === Array。许多 JavaScript 程序员宁愿从不使用松散相等,因为 == 的规则令人困惑。

使用 && 和 .constructornullundefined 的工作方式与 Array.isArray() 的效果相同:它返回 false,正如你所希望的那样。

但是,未声明的变量在尝试访问 .constructor 属性时仍会引发 ReferenceError。你可以在数组检查之前使用 typeof 检查该值是否“undefined”以解决该问题。 

如果数组变量实际上是未声明的怎么办?

你可能不确定是否实际上已经声明了可能是数组的变量。让我简单谈谈检查未声明的数组。

提醒一下,访问尚未声明的变量将引发 ReferenceError,而已声明但未分配特定值的变量将具有 undefined 值。

值得庆幸的是,typeof 关键字将为尚未声明的变量返回“undefined”,与未定义的值相同,但不会抛出 ReferenceError,因为该变量还没有被声明。

这意味着我们可以将 Array.isArray() 包装在 typeof 调用中,以使其对未声明的变量具有鲁棒性。这是一个例子:

 

或者,我们可以使用 try...catch 块来捕获潜在的 ReferenceError,但 typeof 对未声明的变量同样有效。

如何在 JavaScript 中检查空数组? 

相反,如果我们想检查一个数组是否为空,我们可以检查它的 .length 属性——一个空数组的 .length0

同样,我们需要确保我们正在使用一个已声明的变量,该变量已经分配了一个绝对是数组的值。

但是,假设我们从 Array.isArray([]) 得到 true,那么 [].length > 0 将确认我们的数组不为空。这是一个代码片段:

 

同样,我们正在利用 && 作为短路运算符。因为它在错误陈述上“短路”,所以我们永远不会达到上面示例中的 .length 调用。这正是我们想要的,因为 .length 不适用于大多数原语,如数字或其他类型的对象。

总结

本文详细介绍了5 种不同的检查 JavaScript 数组的方法。我在编码时通常使用 Array.isArray() ,有几个原因:

  • Array.isArray() 快速且得到广泛支持。
  • Array.isArray() 是显式的,使您的代码更具可读性。
  • Array.isArray() 为 null 和未定义返回 false。 

有时,在我担心未声明变量的罕见情况下,我会将数组检查包含在 if(typeof !== "undefined") 语句中。

参考文章

相关文章

标签: 对象  数组  
x
  • 站长推荐
/* 左侧显示文章内容目录 */