Javascript数组方法(译)

在JavaScript中,数组可使用Array构造函数来建立,或使用[]快速建立,这也是首选的方法。数组是继承自Object的原型,而且他对typeof没有特殊的返回值,他只返回'object'。javascript

运行[] instanceof Array他会返回ture。虽然结果是这样,但也有复杂的类数组对象,如字符串或arguments对象,但arguments对象并不是是Array的实例,但他却拥有length属性,并且他的值是能够被索引的,所以他能够像一个数组那样被遍历。

这本文中,我将介绍数组原型的一些方法,并探讨每一种方法的用途:
使用.forEach 来作遍历 
使用.some and .every 来断言
使用 .join and .concat 来合并
使用 .pop, .push, .shift, and .unshift 来操做栈和队列
使用 .map 映射模型
使用 .filter 来作查询
使用 .sort 来作排序
使用 .reduce, .reduceRight 来计算
使用 .slice 来复制
.splice 的用途
使用 .indexOf 来查找
in 操做符介绍
.reverse 的用途

使用 .forEach来遍历
======
这是原生Javascript数组最简单的方法之一,但他不支持IE6~8。

forEach 会在遍历数组中的每一个元素时就执行一次回调函数,并传递三个参数。
value 当前的数组元素
index 当前元素在数组中的位置
array 对数组的引用

此外,咱们还能够传递一个可选的参数,做为每一个函数调用时的上下文(this),看下面例子:html

['_', 't', 'a', 'n', 'i', 'f', ']'].forEach(function (value, index, array) {
    this.push(String.fromCharCode(value.charCodeAt() + index + 2))
}, out = [])

out.join('')
// <- 'awesome'


这里使用了.join,这是咱们尚未说起到的,但日后咱们会再做介绍,在这个例子中,他能够链接数组中的不一样元素,能够达到相似字符串拼接的效果。out[0] + '' + out[1] + '' + out[2] + '' + out[n].

咱们不能停止forEach循环和抛出异常,在这些情景下,咱们能够选择使用其余可用的方法。


使用 .some和.every来断言
=====

若是你曾使用过.Net的 enumerables,也许你熟悉.Any(x => x.IsAwesome) and .All(x => x.IsAwesome).
这些方法和.forEach很是类似,他们一样地给回调函数传递了value, index 和array, 你也一样的能够给他传入二个可选参数来做为回调函数的上下文。MDN是这样来描述.some的:

".some方法能够在遍历数组中的每一个元素时执行回调函数,直到回调函数返回true为止,若是这个元素被发现,.some当即返回true。不然.some会返回false. 回调函数只对数组非空元素的索引调用,并不会对已经被删除或从未被指派的值调用"java

复制代码
max = -Infinity
satisfied = [10, 12, 10, 8, 5, 23].some(function (value, index, array) {
    if (value > max) max = value
    return value < 10
})

console.log(max)
// <- 12

satisfied
// <- true
复制代码

回调函数会在知足条件value < 10时中止执行。.every也是一样的道理,但他的短路是发生在回调函数返回false时。


使用 .join and .concat 来合并
=====
.join方法一般会和.concat方法混淆。.join是建立一个经过分隔符来连接数组中各元素的字符串,若是不提供分隔符,他就会默认以逗号做用分隔符。.concat经过他的源数组建立一个新的数组。

.concat 能够传入多个参数: array.concat(val, val2, val3, valn)
.concat 是能够返回一个新的数组
array.concat() 若是不传入参数则将会返回一个新的浅拷贝数组。

浅拷贝意味着副本能够保存着源数组的对象引用。例如:数组

复制代码
var a = { foo: 'bar' }
var b = [1, 2, 3, a]
var c = b.concat()

console.log(b === c)
// <- false

b[3] === a && c[3] === a
// <- true
复制代码


使用 .pop, .push, .shift, and .unshift 来操做栈和队列
===
如今你们都知道能够经过.push方法来往数组中添加元素,但你是否知道.push能够传入多个参数,一次性把多个参数添加到数组后面。如:[].push('a', 'b', 'c', 'd', 'z')

.pop方法和.push方法恰好相反。他将会返回数组中的最后一个元素,而且同时从数组中删除这个元素。若是数组为空,则会返回void . (undefined)。使用.push和.pop,我能够很是容易地建立一个LIFO(last in first out) 的栈。app

复制代码
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(fist in first out) 的队列。函数

复制代码
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) 能够容易地遍历数组。this

复制代码
list = [1,2,3,4,5,6,7,8,9,10]

while (item = list.shift()) {
    console.log(item)
}

list
// <- []
复制代码


使用 .map 映射模型
=========
.map在遍历数组中的每一个元素时执行一次回调函数,而且会返回一个新的数组。回调函数只会对数组的元素索引执行,并不会对已删除或没元素的索引而执行。

Array.prototype.map方法和.forEach,.some和.every有着类似的地方:.map(fn(value, index, array), thisArgument)。spa

复制代码
values = [void 0, null, false, '']
values[7] = void 0
result = values.map(function(value, index, array){
    console.log(value)
    return value
})

// <- [undefined, null, false, '', undefined × 3, undefined]
复制代码

undefined × 3 的意思是.map不会在一个删除或者未定义的数组元素上执行,但他们会继续保留在结果数组上。映射是对数组的转化是很是有用的。看下面示例:prototype

复制代码
// 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 objects
items.map(function (item) {
    return {
        id: item.id,
        name: computeName(item)
    }
})
复制代码


使用 .filter 来作查询
======

.filter在遍历数组中的每一个元素时执行一次回调函数,而且回调函数返回的true时,他将会保存这当前元素,最后返回一个新数组。回调函数只会对数组的元素索引执行,并不会对已删除或没元素的索引而执行。不传递到回调函数的元素将会被简单的忽略,而且不会在新的数组中出现。code

复制代码
[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, '']
复制代码


使用.sort 来作排序
========

若是不提供回调函数,元素将会经过转换为字符后而且按照在字典中的顺序来排序。例如在字典中"80"在"9"的前面,但若是按数字来排序,则9在80以前。

就像大多数的排序函数同样,Array.prototype.sort(fn(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]
复制代码


使用 .reduce, .reduceRight 来计算
========
这两个方法都有着一样的特性:
.reduce(callback(previousValue, currentValue, index, array), initialValue).
在每个回调函数执行时,previousValue将会被返回。初始化时initialValue将会被传入回调函数,currentValue包含着当前的元素,index表示该元素的在数组中的位置。array为数组的引用。
一个经典的.reduce例子就是加法函数。

复制代码
Array.prototype.sum = function () {
    return this.reduce(function (partial, value) {
        console.log(partial, ",",value)
        return partial + value
    }, 0)
};

[3,4,5,6,10].sum()
// <- 28
复制代码


若是说咱们要合并一些字符串,咱们可能会用到.join方法来达到目的。可是在下面这个例子中,.join方法就可能达不到咱们的要求了,除非这些对象都有valueOf或者toString属性。但咱们可使用.reduce方法来轻松实现合并各对象为字符串。

复制代码
function concat (input) {
    return input.reduce(function (partial, value) {
        if (partial) {
            partial += ', '
        }
        return partial + value.name
    }, '')
}

concat([
    { name: 'George' },
    { name: 'Sam' },
    { name: 'Pear' }
])
复制代码

注:reduce和reduceRight的区别是,reduce 是从数组左到右开始遍历,而reduceRight是从数组右到左开始遍历。


使用 .slice 来复制
======
Array.prototype.slice can be used to convert array-like objects into real arrays.
和.concat类似,能够经过不传递参数给.slice方法来复制源数组。.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 }]


除此以外,咱们还能够把类数组转换为真正的数组以后,而且去除数组前面几个元素。

复制代码
function format (text, bold) {
    if (bold) {
        text = '<b>' + text + '</b>'
    }
    var values = Array.prototype.slice.call(arguments, 2)

    values.forEach(function (value) {
        text = text.replace('%s', value)
    })

    return text
}

format('some%sthing%s %s', true, 'some', 'other', 'things')
// <- <b>somesomethingother things</b>
复制代码


.splice 的用途
====
.splice也是一个经常使用的数组方法。你能够经过.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 13

console.log(source)
// <- [1, 2, 3, 8, 8, 8, 8, 8, 9]
复制代码


使用 .indexOf 来查找
=========
经过使用.indexOf方法,咱们能够找到元素在数组中的位置。若是找不到,将会返回-1。若是要查找,一般我会这样写比较a === 'a' || a === 'b' || a === 'c',但在这个场景,你能够['a', 'b', 'c'].indexOf(a) !== -1。

要注意的是,若是是查找数组中的对象,那么你要提供相同的对象引用。第二个参数是表示从数组中的哪一个位置开始搜索。

复制代码
var a = { foo: 'bar' }
var b = [a, 2]

console.log(b.indexOf(1))
// <- -1

console.log(b.indexOf({ foo: 'bar' }))
// <- -1

console.log(b.indexOf(a))
// <- 0

console.log(b.indexOf(a, 1))
// <- -1

b.indexOf(2, 1)
// <- 1
复制代码


若是你但愿反顺序查找,你可使用.lastIndexOf。

in 操做符介绍
========
.indexOf 和 in操做符很是容易混淆。

复制代码
var a = [1, 2, 5]

1 in a
// <- true, but because of the 2!

5 in a
// <- false
复制代码

问题就在这里,in操做符是用于检查一个对象的键,而不是查找一个元素在数组中的位置。固然这比.indexOf快。

var a = [3, 7, 6]

1 in a === !!a[1]
// <- true

in操做符相乎是把传递进来的值转换为布尔值。!!表达式是能够把值隐式转换为布尔值。

关于.reverse
=========
这个方法是能够把数组中的元素位置反转。

var a = [1, 1, 7, 8]

a.reverse()
// [8, 7, 1, 1]

这里并不是返回一个副本,而是直接修改了数组的自己。


译自:
http://flippinawesome.org/2013/11/25/fun-with-javascript-native-array-functions/

原博客:http://www.cnblogs.com/zzbo/p/3541847.html

相关文章
相关标签/搜索