这个数据类型到底是Array还是Object?

最近在研究Vue的源码,在数组变异实现的时候有有一个地方存在疑问:Vue是通过设置一个数组重新对push、pop等数组方法进行封装,从而能监听到数组的变动,如下:

const arr = [];
[
  'push',
  'pop',
  'shift',
  'unshift',
  'splice',
  'sort',
  'reverse'
].forEach(method => {
    arr[method] = function () {
        console.log('监听到数组变动')
    }
})

那么问题来了,arr这个变量是以一个数组定义的,按道理应该可以直接通过数组下标arr[0]来访问里面的元素,可事实上这样是返回的是undefined,通过key的形式取值是可以的,例如arr['push']

图片描述

再从控制台查看arr,看到他的length居然是0!如下:

图片描述

上面两个迹象可以看到这个arr的表现跟Object是完全一样的,但是当我对arr使用Array.isArray(arr)时,结果返回的是true,说明arr是一个数组,请问这个arr到时是个什么类型呢?

阅读 3.5k
4 个回答

感谢 @toBeTheLight 和 @忆先 的回答,他们的答案给了我一点启发,我重新查了下资料来自问自答吧,这主要是常规数组关联数组的区别:
常规数组已0、1、2...作为数组的索引,取值的时候也是根据数组下标进行索引,常见的数组就是这样的形式,如:

a = [];
a["1"] = {"string1":"string","string2":"string"};
a["2"] = {"string1":"string","string2":"string"}

JavaScript会自动转换string的index为number:

a = [];
a[1] = {"blah"};
a[2] = {"blah"};

这是一个常规数组。

关联数组:以key作为数组的索引,其实跟普通的对象没什么区别:

b["key1"] = {"string1":"string","string2":"string"};
等价于:
b.key1 = {"string1":"string","string2":"string"};

其实这个就是@忆先所说,可以理解成python中的dict,因为js里面数组也是一个对象,b.key1的行为也是相当于给这个数组添加一个key而已,因此此时b的长度还是0.
参考:
Javascript array length incorrect on array of objects

就是个数组啊。
数组的index是个比较特殊的key。

var arr = [1,2,3]
arr.value = 'arr'
arr.value //'arr'
arr.length //3

就是一个简单的关联数组,相当于Java的map,Python的dict,
可以当字典理解,按key取值,当然也有长度。

这个arr还是个空数组 不过被重写了push/pop等方法

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题