JavaScript中原生Array数组方法详解

来源 | http://www.fly63.com/article/detial/9692
- 循环.forEach 
- 断言.some,.every 
- 连接与合并.join,.concat 
- .pop,.push,.shift,.unshift 
- 模型映射.map 
- 过滤.filter 
- 排序.sort 
- 聚合.reduce,.reduceRight 
- 截取.slice 
- 删除插入.splice 
- 发现值.indexOf 
- 在操作符中发现键 
- 颠倒.reverse 
1.forEach()
- 值当前值 
- index当前位置,索引值 
- array当前数组 
['_', 't', 'a', 'n', 'i', 'f', ']'].forEach(function (value, index, array) {this.push(String.fromCharCode(value.charCodeAt() + index + 2))}, out = [])out.join('')// <- 'awesome
forEach的缺陷是既不能中断循环,也不能引发异常。
2.some(),every()
这两个方法类似“断言”(assert),返回一个布尔值,表示判断数组成员是否符合
某种条件。对于foreach,同样接受一个包含值,索引和数组的变量函数作为参数,而且也可以指定上下文中的这一点。
有些方法是只要一个成员的返回值是真,则整个某些方法的返回值就是真实的,否则返回假。
每个方法是所有成员的返回值都是真实的,整个每一个方法才返回真,否则返回false。
max = -Infinitysatisfied = [10, 12, 10, 8, 5, 23].some(function (value, index, array) {if (value > max) max = valuereturn value < 10})console.log(max)// <- 12satisfied// <- true
3.join()和concat()
这两个方法容易搞混,加入是将多个内部各个成员用分隔符连接成一个串联,分隔符交替是,, concat用于多个交错的合并。成员的后部,然后返回一个新副本,原副本不变。
var a = { foo: 'bar' }var b = [1, 2, 3, a]var c = b.concat()console.log(b === c)// <- falseb[3] === a && c[3] === a// <- true
4.pop,.push,.shift和.unshift
每个人都知道往上面的末尾添加一个元素是用push方法,但你知道可以一次性添加多个元素吗,像这样[] .push('a','b','c','d', 'z')。
pop是push方法的逆操作,移除了多个最后一个元素同时返回这个元素,如果是空分配则返回undefined,使用这两个方法很容易实现LIFO(后进先出)栈结构。
function Stack () {this._stack = []}Stack.prototype.next = function () {return this._stack.pop()}Stack.prototype.add = function () {return this._stack.push.apply(this._stack, arguments)}stack = new Stack()stack.add(1,2,3)stack.next()// <- 3
相应的,我们可以通过.unshift和.shift实现一个FIFO(先进先出)类型。
function Queue () {this._queue = []}Queue.prototype.next = function () {return this._queue.shift()}Queue.prototype.add = function () {return this._queue.unshift.apply(this._queue, arguments)}queue = new Queue()queue.add(1,2,3)queue.next()// <- 1
使用.shift(或.pop)很容易用while循环清空一个数组,如下:
list = [1,2,3,4,5,6,7,8,9,10]while (item = list.shift()) {console.log(item)}list// <- []
5.map()
方法
签名为forEach,.map(fn(value,index,array),thisArgument)。
values = [void 0, null, false, '']values[7] = void 0result = values.map(function(value, index, array){console.log(value)return value})// <- [undefined, null, false, '', undefined × 3, undefined]
undefined×3表明在某种程度上函数不会在已删除或未赋值的成员执行,而是自己返回包含在返回数组中。地图在映射或转换排列时非常有用,下面有个例子:
// casting[1, '2', '30', '9'].map(function (value) {return parseInt(value, 10)})// 1, 2, 30, 9[97, 119, 101, 115, 111, 109, 101].map(String.fromCharCode).join('')// <- 'awesome'// a commonly used pattern is mapping to new objectsitems.map(function (item) {return {id: item.id,name: computeName(item)}})
6.filter()
filter方法用于过滤数组成员,满足条件的成员组成一个新副本返回。
正在使用,.filter(fn(value,index,array),thisArgument)。
[void 0, null, false, '', 1].filter(function (value) {return value})// <- [1][void 0, null, false, '', 1].filter(function (value) {return !value})// <- [void 0, null, false, '']
7.sort(compareFunction)
排序方法对数组成员进行排序,默认是按照字典顺序排序。排序后,原数组将被改变。
像大多数的排序函数一样,Array.prototype.sort(FN(A,B))接受一个回调函数用于比较a,b的大小,而且为以下三种情况之一:
- 如果a在b之前,则返回值<0 
- 如果a和b都等效,则返回值=== 0 
- 如果a在b之后,则返回值> 0 
[9,80,3,10,5,6].sort()// <- [10, 3, 5, 6, 80, 9][9,80,3,10,5,6].sort(function (a, b) {return a - b})// <- [3, 5, 6, 9, 10, 80]
8.reduce(),reduceRight()
Reduce函数一开始很难理解,这些函数会循环数组,从左向右(.reduce)或从右向左(.reduceRight),每次函数执行时会接受之前的部分结果,最终返回值是单一聚合的值。
两个方法具有相同的语法:
reduce(callback(previousValue, currentValue, index, array), initialValue)Array.prototype.sum = function () {return this.reduce(function (partial, value) {return partial + value}, 0)};[3,4,5,6,10].sum()// <- 28
9.slice()
slice()方法用于提取目标片段的一部分,返回一个新副本,原先的位置不变。
arr.slice(start, end)它的第一个参数为起始位置(从0开始,会包括在返回的新细分之中),第二个参数为终止位置(但该位置的元素本身不包括内部)。如果省略第二一个参数,则一直返回到原始副本的最后一个成员。
与concat()类似,slice()如果没有任何参数则返回原始数组的浅表副本。Array.prototype.slice可以用作将类的对象转换成真正的数组。
Array.prototype.slice.call({ 0: 'a', 1: 'b', length: 2 })// <- ['a', 'b']
concat做不到,它会返回一个包含目标对象的层叠。
Array.prototype.concat.call({ 0: 'a', 1: 'b', length: 2 })// <- [{ 0: 'a', 1: 'b', length: 2 }]
10.splice()
.splice是我最喜欢的数组原始数组方法,它允许您在一次性在同一个位置删除,插入元素,注意:这个函数会改变原数组。
var source = [1,2,3,8,8,8,8,8,9,10,11,12,13]var spliced = source.splice(3, 4, 4, 5, 6, 7)console.log(source)// <- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ,13]spliced// <- [8, 8, 8, 8]
你可能注意到了,它会返回被删除的元素,这个常用于循环被删除的元素,你之前可能忘记了。
var source = [1,2,3,8,8,8,8,8,9,10,11,12,13]var spliced = source.splice(9)spliced.forEach(function (value) {console.log('removed', value)})// <- removed 10// <- removed 11// <- removed 12// <- removed 13console.log(source)// <- [1, 2, 3, 8, 8, 8, 8, 8, 9]
11.indexOf(),lastIndexOf()
indexOf方法返回给定元素在多个中第一次出现的位置,如果没有出现则返回-1。
var a = { foo: 'bar' }var b = [a, 2]console.log(b.indexOf(1))// <- -1console.log(b.indexOf({ foo: 'bar' }))// <- -1console.log(b.indexOf(a))// <- 0console.log(b.indexOf(a, 1))// <- -1b.indexOf(2, 1)// <- 1
lastIndexOf方法返回给定元素在多个中最后一次出现的位置,如果没有出现则返回-1。
注意,这两个方法不能用来搜索NaN的位置,即无法确定该成员是否包含NaN。
这是因为这两个方法内部,使用严格的内部运算符(===)进行比较,而NaN是唯一一个不等于自身的值。
12.在操作符中
在用于查找关键中,索引速度则是查找值。当然速度快于indexOf。
var a = [1, 2, 5]1 in a// <- true, but because of the 2!5 in a// <- falsevar a = [3, 7, 6]1 in a === !!a[1]// <- true
在操作符跟把相应位置的值转换为布尔值类似。表达式常用于将一个值取反然后再取反,这是一种高效的将真值转为布尔值的方式。
13.reverse()
注意,该方法将更改原始数组。
var a = ['a', 'b', 'c'];a.reverse() // ["c", "b", "a"]a // ["c", "b", "a"]

