在之前介绍模拟函数重载效果的时候,我们看到JS中的函数中,其实有一个“隐形”的东西来存储实参所有的实参,这个东西就是arguments对象。但在实际使用过程中它的使用方式和数组简直一模一样,用起来感觉就是数组,没有任何毛病,但实际上它并不是一个数组。

arguments看起来,用起来都像是数组
1 调用方法类似:都可以通过中括号下标的形式来访问具体某个参数。
2 有length属性:直接可以获取实参的个数。
3 和数组一样,用中括号将内容包含起来。

究竟是不是数组?
结合我们之前所学关于数组的知识点,刚好把它们串起来,从三个角度来验证下arguments是不是数组。
1 如果是数组,就可以使用前面介绍过的数组的方法,比如用push函数给arguments插入一个元素。

结果报错,arguments并不像正常的数组一样,有push函数
2 正面确认下,用我们之前判断数组的方法来判断一下:

结果为false,直接说明arguments不是数组。
3 这一切从控制台看的更为真切:

通过toString函数执行结果可以看出,arguments其实是“[object Arguments]”,其实将其直接打印出来的__proto__属性值就可以看出,arguments是Object。但是,这个arguments对象又跟我们看到的普通(正常)对象又有区别,因为一般的对象是大括号,而arguments对象是中括号,这一点又像数组。

综上,arguments本质上是对象,而且是具有数组特性的对象,包括表现形式都用中括号,这种就是艰巨对象和数组特性的数据类型就叫做类数组。
横空出世:类数组
为了更深入的理解类数组,我们一步步来构造一个类数组。。
先从一个普通对象car开始,特别之处在于增加了数字作为属性,以及增加一个length属性,这样,我们就基本可以模拟出数组的使用方式了,并且仍然保持了对象的特性,如下图

但这个时候,虽然有点像了,但还有两点没有做到,一就是这个时候仍然不能使用数组的方法,二就是该对象打印出来还是使用大括号,也就是仍然只是一个对象。下面给这个对象添加数组的方法试试,以push和splice连个函数为例。

可以看到,在Object对象原型上增加数组的push和splice方法后,该对象之前的大括号也变成了数组的中括号,下面试试新增加的方法是否有效

可以看到,push方法成功将新的元素添加到对象中,类数组car就创建完成了。
需要特别说明的是:
1 数组的方法需要挨个添加到类数组中,需要哪个就添加哪个,并不是一次吧数组的所有方法一次性搬过来了
2 在对象中添加数组的位置,除了刚刚的在对象原型上添加,还可以在类数组中单独添加,这样只对本类数组有效,刚刚的方法会导致之后所有的对象都自带添加的数组方法。

之后创建的对象都自带数组操作
在类数组对象中添加数组的操作方法,只在本对象有效,不影响其他对象。

过程有点复杂,但是也正是通过这些,让我们透过表面的数据类型,有机会窥探原型,数组和对象的背后,看到 一些近乎颠覆三观的知识。类数组是一个难点,但是因为它兼具对象和数组的特性,非方便,所以经常要使用到,所以必须理解准确到位,使用熟练。
如果有哪里讲的不对或者需要补充,欢迎评论交流。最后来个很奇葩的大厂笔试题,以上知识学懂没学懂,欢迎大家评论区提交答案试试。

发表评论