探究 JavaScript 中的 Array

吐槽君 分类:javascript

前言

本文探究一下 Array ,并实现 Vue 中对数组下标操作进行响应式化, Vue 中的数组操作可看这篇文章 Vue 数组操作及源码分析

什么是 Array

JavaScript的 Array 对象是用于构造数组的全局对象,数组是类似于列表的高阶对象。

数组是引用数据类型,可通过字面量和 Array() 构造函数来创建,其中使用 Array() 构造函数时,若值传入一个实参,且为数字时,则生成一个 length 为该实参的空数组。

数组1.png

Array 下标操作

数组2.png

备注: 这里我在写示例时有一个小插曲,我是在 chrome 的 console 中,将代码全部执行完之后然后再打开折叠的输出内容,所以 chrome 应该是在我点击哪个三角形之后去读取变量 a 的内容,所以导致打印出来的内容一样,与 Array 无关,也没什么用,只是记录一下

Array 的方法

Array 的方法在 MDN 中已经讲的非常清楚了,这里我作一些理解和总结

  1. 数组也是对象,数组的原型对象为 Array.prototype ,拥有 length 属性。

数组3.png

备注: 这里我使用字面量定义数组 a 时,键名是数字 1 ,但是也并没有报错,应该是自动转成字符串了,虽然没报错,但是不建议这样使用,不符合命名规范,记一下

  1. 数组的下标其实是字符串,这个知识点从上面的例子可以看出,所以我们定义一个拥有 length 的对象,然后将原型改为 Array.prototype 也可以获得一个数组对象,但是其与使用字面量或构造函数定义的数组还是不同的,可以通过一些例子来证明

数组4.png

从图中可以看出,我们通过字面量定义数组 a ,我们按照 1 中的说法将 a 变成数组,但是我们操作 length 时,下标为 10 的属性并没有因为 length 的改变而被截掉,而是作为对象的属性 (这是 chrome 浏览器中的表现,其他引擎没有试,因为这个区别反正也是无用的知识,突发奇想测试出来的)

  1. 数组的长度是 length ,而不是里面存了多少元素,当然,数组中的元素数小于 length ,使用一些涉及到数组长度的方法是根据 length 来操作的,比如 pop 弹出的是 [length -1] 元素,如果该下标元素为空,则返回 undefined

Vue2 中响应式化下标操作的简单实现

根据前面的学习,数组中的元素其实也可以类比键值对形式,而 Vue 中的响应式化就是通过 Object.defineProperties() 来将属性描述符设置为访问器描述符,即重写属性的 get()set() ,而我们通过对下标进行响应式化即可监听对数组的下标操作,即重写下标的 get()set() 即可

var Observer = function Observer (value) {
  this.value = value;
  this.dep = new Dep();
  this.vmCount = 0;
  def(value, '__ob__', this);
  if (Array.isArray(value)) {
    if (hasProto) {
      protoAugment(value, arrayMethods);
    } else {
      copyAugment(value, arrayMethods, arrayKeys);
    }
    // this.observeArray(value);
    this.walkArray(value)
  } else {
    this.walk(value);
  }
};

Observer.prototype.walkArray = function walkArray (obj) {
  obj.forEach((item, index) => {
    defineReactive$$1(obj, index) // 在这里对其下标进行响应式化
  });
}
 

数组6.png

但是 length 无法进行响应式化,因为 length 的属性描述符不允许被修改

数组5.png

回复

我来回复
  • 暂无回复内容