【JS进阶向】从造数组数据说开去

OnePiece  |  2019. 01. 05   |  阅读 599 次

前言

前后端合作刚开始开发某个项目时,后端api接口基本上是不能一蹴而就的。但是api接口返回的数据接口可以尽快定下来。而前端在制作功能页面时,经常需要数据才能处理的得心应手。而不管是用mock,还是临时变量赋值,都涉及到造数据。一般来说,数据类型以数组居多。接下来,就从造数组数据说开去。

内容

伪数组

数组最基本的特征是有length属性,有length属性的对象(非数组)称作伪数组。伪数组是不能够直接调用数组的方法的。不过以下两种方法可以将伪数组转为数组。

Array.prototype.slice.call();

const obj = {0:'a',1:'b',length:2}; // 伪数组
const arrLike = Array.prototype.slice.call(obj);  
console.log(arrLike);  // ["a","b"]

Array.from()

const obj = {0:'a',1:'b',length:2}; // 伪数组
const arrLike = Array.from(obj);
console.log(arrLike);   // ["a","b"]

生成可循环的长度为length的数组

可以通过以下3种方法生成可循环的长度为3的数组,结果都是在chrome打印的

Array(length).fill(undefined)

const arr = Array(3).fiil(undefined);
console.log(arr);   // [undefined, undefined, undefined]

Array.apply(null, Array(length)) === Array(...Array(length))

const arr = Array.apply(null, Array(3));
console.log(arr);   // [undefined, undefined, undefined]

Array.from({length})

const arr = Array.from({length: 3});
console.log(arr);   // [undefined, undefined, undefined]

empty?

那么有人可能会疑惑为什么不直接用Array(3)呢?我们先打印Array(3)在chrome下输出什么,以及,它是否可循环3次。

const arr = Array(3);
console.log(arr);   // [empty × 3]
arr.forEach(item => console.log(item)); // 回调函数未执行,循环0次。

那么这个chrome下的empty究竟是什么东西呢。我们先来看看还有什么情况会出现这个empty

const arr = [1,2,3];
delete arr[1];
console.log(arr);   // [1, empty, 3];

arr.forEach(item => console.log(item)); // 1,3 实际循环了2次。

arr.length = 5;
console.log(arr);   // [1, empty, 3, empty × 2]

arr[6] = 7;
console.log(arr);   // [1, empty, 3, empty × 3, 7]

由上述forEach可知,数组的循环次数不一定等于数组的长度。而是等于数组的长度减去empty的个数。

我们知道数组本质上也是对象。那么我们就把数组当成对象,以对象看待试试。

const arr = [1,2,3];
delete arr[1];  // output: [1, empty, 3]
console.log(Object.getOwnPropertyDescriptors(arr));

Object.getOwnPropertyDescriptors() 方法用来获取一个对象的所有自身属性的描述符。输出如下

delete操作符用于删除对象的某个属性,数组也是对象,删掉之后输出上面的结果不是很正常吗。但是,等等。

也就是说数组中打印出来的empty等于对象中不存在的属性。即empty在打印结果中的作用就是占位用的,其意义是,举个例子,[1, empty, 3]这个对象的自身属性1,已经不存在了。用对象表示的话,就是{ 0: 1, 2: 3, length: 3 }。另外数组的for循环或者循环方法应该是对象的for...in的数组展示。那么元素为empty的不执行回调函数,也可以理解了。


回到Array(3).fill(undefined),既然Array(3)输出[empty × 3],那么fill之后为何会输出[undefined, undefined, undefined]呢,不是说好的回调函数不执行了吗。咳咳,详情可以看fill的polyfill。可以看到fill的根据是数组的length属性。毫无疑问,Array(3)的length就是3。

我们知道Array(1,2,undefined)会生成[1, 2, undefined],所以Array(...Array(3))按chrome的empty填充的话,其实就是Array(empty, empty, empty)。其实相当于{0: empty, 1: empty, 2, empty, length: 3}。而对象中不存在的属性,比如

const a = {};
console.log(a.b);   // undefined

还是会输出undefinedempty实际上并不存在,所以Array(...Array(3))输出[undefined, undefined, undefined]没毛病。

Array.from({length : 3})输出[undefined, undefined, undefined],也是以length为基准生成数组的,详见Array.from()

以上都清楚了以后,造数组数据不是信手拈来的事么。

分享到

   
小读electron系统架构
加入我们