Que's Blog

WebFrontEnd Development

0%

Array整理二

JavaScript数组支持简况

简单回忆一下JavaScript原生对数组的支持,最常用的基本是,push,pop,shift,unshift这类。
实际上,我甚至相信很多写了很多年JavaScript的人,可能会pop,unshift和shift到底是栈还是队操作这种搞混——我以为这种事情并不奇怪,前端甚至很多后端,在具体业务中实际上也很少在数据堆栈结构中不停进栈(队)出栈(队)操作。

而且,相比后端对数组方法完善的方法集成,前端的数组操作,只能算是马马虎虎,这么多年过去,基本上还是堆和栈操作的老三样——不过很多前端确实也不需要复杂的处理方法。

JavaScript数组的栈和队

栈操作 –>LIFO(Last in first out)

栈操作的特点就四个字:后进先出

  • pop 出栈操作,删除并返回最后一个数组元素
  • push 入栈操作,返回添加后的数组长度(直接操作数组)

队操作 –> FIFO(First in first out)

队操作的特点是先进先出

  • unshift 入队操作,在数组头部添加一个元素,返回添加后数组长度
  • shift 出队操作,在数组头部删除一个元素并将其返回

栈操作和队操作的简单对比总结

首先说下相同的地方:

  • 出栈操作(pop)和出队操作(shift)都是将特定删除的元素直接从数组中删除并返回
  • 入栈操作(push)和入队操作(unshift)都是将特定元素直接放到数组中,并返回新数组的长度

不同的地方:
一个是FIFO一个是LIFO,这里有个很粗鄙但是很形象的比喻是:

栈操作是吃多了吃不下吐出去,而队则是吃多了拉出去。

数组其他一些方法

除了栈和队操作以外,常见的数组操作方式还有:

  • slice和splice数组切片操作。在切片操作中,它们都可以接受两个参数,一个是数组索引(从0开始),一个要切片的数量。但是slice和splice的不同之处是slice将切片后的数组返回并不会影响原来数组,而splice则直接操作原来数组将切出来的从原来数组删除。

  • join操作,可以将数组指定分隔符号拼接成字符串(响应的,字符串有个split操作,类似join反向操作),缺省分隔符号是”,”。join的作为Array2String的使用场景很多,使用它可以替代”+”来拼字符串和厂商队字符串处理效率的优化,效率要高一些(得益疯狂优化的浏览器内核,这个结论正在被挑战)。

  • concat.这个比较简单,合并数组用的。

  • forEach和map。感觉这两个方法有些容易搞混。

    • forEach(迭代),forEach类似将原料(数组内每个元素)扔进扔进生产机器,扔完以后就不是forEach的活儿了
    • map(收集),map则不同,他不但要挨个扔进原料,还要负责把原料生产出来的产品放进新的盒子里面(不影响原来数组)
  • filter过滤数组,filter是一个非常好用也非常常用的方法,它负责根据条件来过滤符合条件的数组元素并返回。

  • some和every,个人倾向这两个方法是是”验货方法”,some管的比较松,只要有一个能用(符合判断条件)就让过(返回true),而every则管的很严格(符合判断条件),必须全部能用才给过(返回true)。

  • reverse,将数组反转———这个方法说实话项目从来没用到过。

  • sort,排序。

总体来说,原生的数组方法就是这些,这里简单回顾对比一下,具体的使用代码,可以参见以前的文章:Array整理,这里不在赘述。

数组方法分类

这里本来是打算找一找增强数组方法分类,结果找到了原生支持的,实际上前一篇已经有了累死的分类结论,但是没这个好,所以copy一下这个分类,原文载于《js 你不知道的 Array》 (鉴于国内比较混乱的环境,如果这个不是最初原文出处,请联系我修正)

  1. Mutator方法 这些方法可以改变数组自身

    • pop : 移除数组的最后一个元素,返回值是被删除的元素。
    • push : 在数组的末尾添加一个或者多个元素,返回值是新的数组的长度。
    • reverse : 颠倒数组中元素的顺序,原先第一个元素现在变成最后一个,同样原先的最后一个元素变成了现在的第一个,也就是数组的索引发生了变化。
    • shift : 删除数组的第一个元素,返回值是删除的元素
    • sort : 对数组中的元素进行排序
    • plice : 添加或删除数组中的一个或多个元素。
    • unshift : (将废弃)添加一个或者多个元素在数组的开头,返回值是新的数组的长度。
  2. Accessor方法 这些方法不改变数组自身

    • concat : 返回一个包含此数组和其他数组和/或值的结合的新数组
    • indexOf : 返回第一个与给定参数相等的数组元素的索引,没有找到则返回-1
    • join : 将所有的数组元素连接成一个字符串
    • lastIndexOf : 返回在数组中搜索到的与给定参数相等的元素的最后(最大)索引
    • slice : 返回数组中的一段。
    • toString : 返回代表该数组及其元素的字符,重写Object.toString 过程.
    • valueOf : 重写Object.valueOf过程。
  3. 循环(迭代) 方法

    • filter : 对数组中的每一个元素调用参数中指定的过滤函数,并将对于过滤函数返回值为true的那些数组元素集合为新的数组返回。
    • forEach : 对数组的每一个元素依次调用参数中指定的函数。
    • every : 如果数组中每一个元素都满足参数中提供的测试函数,则返回真
    • map : 创建一个新数组,新数组中含有,分别对于原来数组的每一个元素调用一个给定函数的结果
    • some : 如果数组中至少有一个元素满足参数函数的测试,则返回true。

数组的增强

说完JavaScript原生数组支持,这里来说一说数组方法的扩展和增强。
常见的数组增强在各个辅助库里面其实都会包含,这里仅仅贴一段之前的练习代码。聊做参考:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121

/**
* desc:判断指定元素存在于指定数组中
* @returns {boolean} 返回是否含有
*/
function contains(src,target){
return target.indexOf(src)>-1;
}

/**
* desc:移除特定index的元素
* @param arr
* @param index
* @returns {boolean} 返回操作是否成功
*/
function removeAt(arr,index){
//splice直接操作数组
return !!arr.splice(index,1).length;
}

/**
* desc:移除数组中元素
* @param array
* @param ele 移除元素
*/
function remove(array,ele){
return array.filter(function(e) {
return ele != e;
})
}

/**
* desc:对数组进行乱序
*/
function shuffle(array){
var tmp = [],len = array.length;
for(var a= 0;a<len;a++){
var r = this.random(array); //随机选一个出来
tmp.push(r); //压入目标数组
array = this.remove(array,r);//从数组中删除元素
}
return tmp;
}

/**
* desc:随机选出数组
* @param array
*/
function random(array){
return array[Math.floor(Math.random()*array.length)];
}

/**
* desc:平坦化处理,将内部二维数组转为一维数组
*/
function flatten(){

}

/**
* desc:对数组元素进行去重
* @param array
* 相关参考 http://www.cnblogs.com/wteam-xq/p/4732351.html
* 1.遍历数组法 2.对象键值对法 3.数组下标判断法 4.排序后相邻去除法 5.优化遍历数组法
*/
function unique(array){
var n = new Array(0); //结果数组
n.push(array[0]); //先添加第一个元素进去
//从第二项开始遍历
for(var i = 1; i < array.length; i++) {
//如果当前数组的第i项在当前数组中第一次出现的位置不是i,
//那么表示第i项是重复的,忽略掉。否则存入结果数组
if (array.indexOf(array[i]) === i) n.push(array[i]);
}
return n;
}

/**
* 过滤null&undefined
* @param array
* @returns {Array}
*/
function compact(array){
return array.filter(function (e) {
return e != undefined
})
}

/**
* desc 获取数组中对象的特定值组成的数组
* @param array
* @param name
* @returns {Array}
*/
function fluck(array,name){
var len = array.length,
i = 0,
tmp=[];
for(;i<len;i++){
tmp.push(array[i][name])
}
return tmp;
}

/**
* desc 返回数组最大值
* @param array
* @returns {number}
*/
function max(array){
return Math.max.apply(null,array)
}

/**
* desc 返回数组最小值
* @param array
* @returns {number}
*/
function min(array){
return Math.min.apply(null,array)
}