Description
关于数组的一些事
目录
- 数组与类数组
- 空位
- 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这个属性)
空位
数组的空位指 数组的某一个位置没有任何值,如Array构造函数返回的数组都是空位。
Array(3) // [ , , ]
- 空位不是undefined,undefined依然是有值的。
0 in [undefined, undefined, undefined] //true
0 in [ , ,] // false
更多关于空位,可以看看阮大神的说法
数组方法对空位的处理很不一致,所以要避免产生空位
Vue 是如何监听数组变化的
大家是否注意到,在vue里面直接给 obj.XX = 'test' 这样的写法一般是watch不到的(除非deep: true 直接添加的属性watch不到), 那vue又是怎么能够检测到arr.push arr.pop 之类操作而产生的变化的?其实是重新写了这些方法
在监听value的时候 如果value是数组,则把数组的能够改变数组的方法全部重新写一遍。这样就可以监听到数组的操作带来的变化了。
大家可以看到这里做了一个判断 如果数组有构造该对象的构造函数的原型,则改造原型,如果没有就直接遍历。 为什么这么操作呢?这又牵扯到下一个问题。
为什么es5不能完美继承数组
这是一个著名的讨论题 为什么 es5 不能完美继承数组
数组的方法们
进化与性能
依然盗图 T T
上图展示了数组在内存中存储方式。这个数组保存了 4 个元素,每个元素 4 字节。加起来总共占用了 16 字节的内存区。
假设我们声明了 tinyInt arr[4];,分配到的内存区的地址从 1201 开始。一旦需要读取 arr[2],只需要通过数学计算拿到 arr[2] 的地址即可。计算 1201 + (2 X 4),直接从 1209 开始读取即可
实际上,现代 JavaScript 引擎是会给数组分配连续内存的
—— 如果数组是同质的(所有元素类型相同)。
读取速度貌似没有很大差别, 可能是做了优化。
现代JavaScript引擎 默认分配的是连续内存的。
大家经常用到数组的各种遍历方法,有没有试过各种方法的性能如何?
JavaScript 数组遍历方法的对比
当我思考到这个问题是,也是一阵严肃思考。然后跟着一些各种写测试例子,然后我就蒙了,在控制台,node环境下,或者不同浏览器之间的结果也不太一样。 然后我看到了底下的评论,终于恍然大悟。
数组的方法比较性其实很低。因为我们可以看到用for 循环是最快的,那既然如此为什么我们要有这些方法呢? 我们使用这些数组的方法其实 最应该考虑的是使用场景,什么样的场景需要什么样的方法,这个才是高级语法的意义。至于优化这些方法的速度,那就交给浏览器吧。
过早优化是万恶之源
使用高阶函数替代原始的 for 循环,这样会让代码的可维护性更高,逻辑清晰,语义明确,更加优雅