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

相關文章
相關標籤/搜索