Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于数组的一些事 #7

Open
doreenChenD opened this issue Dec 11, 2018 · 0 comments
Open

关于数组的一些事 #7

doreenChenD opened this issue Dec 11, 2018 · 0 comments

Comments

@doreenChenD
Copy link
Contributor

doreenChenD commented Dec 11, 2018

关于数组的一些事

目录

  • 数组与类数组
  • 空位
  • Vue 是如何监听数组变化的
  • 为什么es5不能完美继承数组
  • 数组的方法们
  • 进化与性能

数组与类数组

  • 数组
    数组对象用来在单独的变量名中存储一系列的值。
  • 数组的判断
    console.log(a instanceof Array); //true (缺陷)
    console.log(a.constructor); // function Array() {[native code]}
    Object.prototype.toString.call(a); //"[object Array]"
    Array.isArray(a); // true
  • 类数组
    典型的类数组例子:
    (1)document.getElementByClassName() 返回的结果
    (2)特殊变量 arguments
  • 类数组转化为数组
    Array.prototype.slice.call(arrlike)
    Array.from(arrlike)
    [...arrlike]
  • 为什么类数组可以使用数组的一些方法(可能是因为数组的某些方法只需要用到length这个属性)
    image

空位

数组的空位指 数组的某一个位置没有任何值,如Array构造函数返回的数组都是空位。
Array(3) // [ , , ]

数组方法对空位的处理很不一致,所以要避免产生空位

Vue 是如何监听数组变化的

大家是否注意到,在vue里面直接给 obj.XX = 'test' 这样的写法一般是watch不到的(除非deep: true 直接添加的属性watch不到), 那vue又是怎么能够检测到arr.push arr.pop 之类操作而产生的变化的?其实是重新写了这些方法

  • vue 2.+
  • src/core/observer/array
    image

在监听value的时候 如果value是数组,则把数组的能够改变数组的方法全部重新写一遍。这样就可以监听到数组的操作带来的变化了。

image

image

大家可以看到这里做了一个判断 如果数组有构造该对象的构造函数的原型,则改造原型,如果没有就直接遍历。 为什么这么操作呢?这又牵扯到下一个问题。

为什么es5不能完美继承数组

这是一个著名的讨论题 为什么 es5 不能完美继承数组

  • 因为Array构造函数执行是不会对传进去的this做任何处理。不止Array,String,Number, Regexp, Object 等等 JS的内置类都不行。
    image

数组的方法们

盗图,忘记出处了 不好意思 T T
image

进化与性能

依然盗图 T T

image
上图展示了数组在内存中存储方式。这个数组保存了 4 个元素,每个元素 4 字节。加起来总共占用了 16 字节的内存区。
假设我们声明了 tinyInt arr[4];,分配到的内存区的地址从 1201 开始。一旦需要读取 arr[2],只需要通过数学计算拿到 arr[2] 的地址即可。计算 1201 + (2 X 4),直接从 1209 开始读取即可

image
如果是上面这样的不连续存储,读起来就相对耗时。

实际上,现代 JavaScript 引擎是会给数组分配连续内存的
—— 如果数组是同质的(所有元素类型相同)。

读取速度貌似没有很大差别, 可能是做了优化。
现代JavaScript引擎 默认分配的是连续内存的。

大家经常用到数组的各种遍历方法,有没有试过各种方法的性能如何?

JavaScript 数组遍历方法的对比
当我思考到这个问题是,也是一阵严肃思考。然后跟着一些各种写测试例子,然后我就蒙了,在控制台,node环境下,或者不同浏览器之间的结果也不太一样。 然后我看到了底下的评论,终于恍然大悟。
数组的方法比较性其实很低。因为我们可以看到用for 循环是最快的,那既然如此为什么我们要有这些方法呢? 我们使用这些数组的方法其实 最应该考虑的是使用场景,什么样的场景需要什么样的方法,这个才是高级语法的意义。至于优化这些方法的速度,那就交给浏览器吧。

过早优化是万恶之源

image

使用高阶函数替代原始的 for 循环,这样会让代码的可维护性更高,逻辑清晰,语义明确,更加优雅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant