类数组对象
故事要从一行代码说起
1 | arr[0] |
请问这里的 arr 一定是一个数组吗?非也,它也可能是一个对象
1 | let arr = { |
前面我们讲过 arguments 这个对象
1 | let say = function (){ |
其大致结构如下
1 | 0: 1 |
我们称 arguments 为类数组对象,正是因为它有这个 length 属性,虽然不能用数组的方法,但是可以通过索引来访问,而且还可以将其转换成数组。
如果一个普通的对象加上一个 length 属性就可以变成一个类数组对象。
之所以今天要讲这个类数组对象,是因为 JavaScirpt 中有很多方法和处理跟类数组对象有关系,所以我们有必要搞清楚这个概念。
转换
ES6 的 Array.from() 可以将一个类数组对象转成数组
1 | let say = function () { |
当然也可以用 ES5 的 slice
1 | Array.prototype.slice.call(arguments) |
接下来我们自己起来创建一个类数组对象
1 | let mans = { |
如果 length 值和实际元素不相等呢?
1 | let mans = { |
可以看到,如果 length 值大于实际元素的数量,不足的将用 undefined 填充,那么反过来呢?
1 | let mans = { |
可见,length 值是决定最终生成数组的长度的,多余的去掉,不足的用 undefined 补齐。好奇心驱使我们继续探索,0 和 1 这两个索引真的有用吗?
1 | mans = { |
所以,这个值是真的有用的,决定了最终的填充索引。细心的同学可能会记得,还有另外一个转换 arguments 的方法
1 | [...arguments] |
那么这个展开运算符可以用到普通的类数组对象上吗?还是亲自测试一下
1 | let mans = { |
可以看到报错了,mans 不是可迭代的,也就证实了 arguments 除了是类数组对象,还是一个可迭代对象,而我们自定义的对象并不具备可迭代功能,所以不能使用展开运算符。
遍历
因为有 length 属性,所以我们可以用 for 循环进行遍历
1 | let mans = { |
除了传统的 for 循环,其它遍历方法可以使用吗?
1 | mans.forEach(item => { |
因为 forEach 是数组的一个方法,只能用于数组,自然就不能用在类数组对象身上了。
1 | for (let man of mans) { |
因为 for…of 也是需要应用到可迭代对象上的。
1 | for (let index in mans) { |
所以只有 for 和 for…in 可以用来遍历类数组对象。
检测
除了 arguments,DOM 元素节点集合也是一个类数组对象,打开任意一个网页,F12 输入下面的代码
1 | document.getElementsByTagName('div') |
可以看到里面有 length 属性,的确是类数组的结构,Array 也有 length 属性,难道这就不会是一个真的数组吗?
倒也是,这个时候就需要利用我们前面讲过的检测数组的方法了
1 | Object.prototype.toString.call(document.getElementsByTagName('div')) |
可以看到这确实不是一个数组。
- 本文作者: 前端圈
- 本文链接: https://lizheguang.github.io/zhaiGuang/2019/02/15/类数组对象/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!