JS 中的类数组,是时候了解了

763 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第 34 天,点击查看活动详情

大家好,我是爱吃鱼的桶哥Z,在前面的文章中,我们梳理了一遍数组中眼花缭乱的 API,其中讲到一个方法 -- Array.from 它可以将类数组转换为可操作的数组对象,今天我们就一起来了解一下关于 JavaScript 中的类数组。

JavaScript 中一直存在一种类数组的对象,它们不能直接调用数组的方法,但是又和数组比较类似,在某些特定的编程场景中会出现,这会让很多初学 JavaScript 的人比较困惑,因此对于类数组还是需要有必要进行了解和学习,让我们开始吧!

JavaScript 中有哪些情况是类数组呢?首先是函数里面的参数对象 arguments,其次还有通过使用 getElementsByTagName/ClassName/Name 获得的 HTMLCollection,以及使用 querySelector 获得的 NodeList,这些都是在 JavaScript 的编程中经常会遇到的类数组对象。

带着问题来学习

首先,我们还是先提出几个问题,带着这几个问题来进行学习,有助于提升加上我们的记忆和理解,问题如下:

  • 类数组是否能够使用数组的方法呢?
  • 类数组可以通过哪些方法转换为数组呢?

带着上述的问题来学习,这样有目的性的学习会比漫无目的的学习更有针对性。

arguments

arguments 是一个对应于传递给函数的参数的类数组对象。我们可以通过一段代码来看一下 arguments 是如何使用的,代码如下:

function foo(name, age, sex) {
    console.log(arguments);
    console.log(typeof arguments);
    console.log(Object.prototype.toString.call(arguments));
}

foo('mac', '18', 'male');

上述代码很简单,只是将 arguments 打印出来,我们可以一起看一下在控制台中打印的数据是什么,如下图所示:

image.png

从上图中可以看到,typeof 修饰的 arguments 返回了一个 object;而通过 Object.prototype.toString.call(arguments) 返回的是一个 object Arguments,而不是一个 object Array,说明 arguments 和数组还是有区别的。

在上图中,我们还看到了 length 属性,它是函数参数的长度,同时它还有一个 callee 属性,我们在一起来看一下 callee 属性是做什么的,代码如下:

function foo(name, age, sex) {
    console.log(arguments.callee);
}

foo('mac', '18', 'male');

上述代码执行后在控制台中打印的内容如下所示:

image.png

通过输出得知 callee 属性就是函数本身,如果在函数内部调用 callee ,则函数会一直执行,直到内存溢出。

HTMLCollection

HTMLCollection 简单来说是 HTML DOM 对象的一个接口,这个接口包含了获取到的 DOM 元素集合,返回的类似是类数组对象。如果用 typeof 来判断的话,它返回的是 'object',并且它是及时更新的,当文档中的 DOM 变化时,它也会随之改变。

NodeList

NodeList 对象是节点的集合,通常是由 querySelector 返回的,它本身是类数组对象,而不是数组。虽然 NodeList 不是数组,但是它也能通过 for...of 来进行迭代,在某些情况下,NodeList 是一个实时合集,也就是说当文档中某些节点发生变化时,NodeList 也会随之变化,我们通过一段代码来了解一下,代码如下:

let list = document.querySelectorAll('input[type=checkbox]');

for (let checkbox of list) {
    checkbox.checked = true;
}

console.log(list);
console.log(typeof list);
console.log(Object.prototype.toString.call(list));

上述代码在控制台中运行后的效果如下图所示:

image.png

类数组的应用场景

我们通过上面的学习已经知道有哪些元素是类数组了,那么类数组有哪些应用场景呢?总结如下:

  • 在函数内部可以直接获取 arguments 这个类数组的值,同时也就可以直接对函数内部的参数进行一些操作,例如:遍历参数操作、定义链接字符串函数等。
  • 通过借助 arguments 可以将参数从一个函数传递到另外一个函数。

如何将类数组转换成数组

在互联网大厂的面试中,经常会有关于类数组转换成数组这样的题目出现,也会问关于 arguments 相关的问题,那么如何才能将类数组转换成数组呢?大致的思路有两种:

  1. 可以通过 callapply 等方法让类数组可以借用数组的方法来转换成数组;
  2. 还可以采用 ES6 中 新增的 Array.from 方法,以及展开运算符的方法来实现类数组对象转换成数组,关于 Array.from 的使用,可以通过上一节的内容进行查看。

上面说的这两个实现的方法是不是很好理解呢?如果你还不是很理解,可以根据文中的介绍自己实现一下相关的代码就能对类数组有一个更清晰的认识了。

最后

关于类数组和数组的区别,我们还是要知道,以及哪些元素是类数组,类数组该如何转换为数组等等,这些问题通过这一节的介绍,我们应该有一个大概的思路了。那么最开始留下的问题,现在你知道该怎么解答了吗?

最后,如果这篇文章有帮助到你,❤️关注+点赞❤️鼓励一下作者,谢谢大家

参考文档

MDN Arguments 对象

往期回顾

『 纯干货』帮你梳理总结眼花缭乱的数组 API

如何实现 new、apply、call、bind ?这篇文章告诉你

JS 中这些继承方式你知道吗?

箭头函数能作为事件监听的回调函数吗?

用操作数组的方式来操作对象,该怎么做?

这几个数组的操作方法你必须知道