你有沒有遇到過如下的場景。coding中當你要處理一個數組的時候,腦海裡只浮現出了forEach;面試中,當面試官讓你說說數組的方法的時候,腦海裡只浮現出了forEach;做夢時當一個數組追殺你,你能想到的只有用forEach來抵抗。如果是,那麼你一定要聽一聽今年數組舉辦的32場演唱會。只要聽完了這 ...
你有沒有遇到過如下的場景。coding中當你要處理一個數組的時候,腦海裡只浮現出了forEach;面試中,當面試官讓你說說數組的方法的時候,腦海裡只浮現出了forEach;做夢時當一個數組追殺你,你能想到的只有用forEach來抵抗。如果是,那麼你一定要聽一聽今年數組舉辦的32場演唱會。只要聽完了這32場演唱會,保證下次當你遇到數組的時候,閉著眼睛都能想出32種方法對付他們。另外,友情提示,結尾有彩蛋。
書歸正傳,數組 是javascript中最常用的引用對象類型之一,在javascript的各種常用的數據結構中,諸如隊列、棧,他們的基本實現方式用的就是數組,因此掌握數組的各項操作也就成為能否自如操控數據結構的要點。截止到ES8,數組目前共有32種方法,可大體分為如下幾種:
-
數組的判斷 1個方法
-
數組內容的判斷 3個方法
-
數組內容的獲取 4個方法
-
數組的構造 6個方法
-
數組的改造 9個方法
-
數組的迴圈遍歷 4個方法
-
數組的累加 2個方法
-
數組轉字元串 3個方法
數組的判斷 1個方法
Array.isArray()
-
語法:Array.isArray(obj)
-
參數:需要檢查的對象
-
返回:true,false
開唱:
判斷數據類型的方法有幾個比如使用typeof,instanceof,那麼為什麼還要有isArray方法呢?
首先說說typeof。眾所周知,javascript有五個基本數據類型undefined,null,number,string,boolean,還有引用數據類型Object,Array,Function,Data,Date,RegExp等。typeof 運算符返回一個用來表示表達式數據類型的字元串,可能的字元串有:"number"、"string"、"boolean"、"object"、"function" 和 "undefined"。這裡面是沒有Array的,無論引用的是什麼類型的對象,它都返回 "object",因此typeOf是不能用來判斷數組的。那麼instanceof呢?通常來講,使用instanceof就是判斷一個實例是否屬於某種類型,這是基於javascript的原型繼承機制的,然而在瀏覽器的環境中如果使用iframe,則可能出現多個不同的全局變數,從而無法發揮instanceof的作用,因此,Array.isArray()成功榮升為最靠譜的檢測方法。但話說回來,其實它的的實現方式還是很簡單的:
-
1 Array.isArray = function(arg) { 2 3 return Object.prototype.toString.call(arg) === '[object Array]'; 4 5 };
需要特別指出的是,Array.isArray()方法是一個靜態方法,只能通過Array對象來調用。
數組內容的判斷 3個方法
Array.prototype.every()
-
語法:arr.every(callback[, thisArg])
-
參數:
-
currentValue 當前值
-
currentIndex 當前值的位置
-
array 所操作的數組
-
callback 斷言數組內每個元素的callback函數
-
thisArg 可選 執行callback時作為this的值
-
返回:t斷言數組的所有元素是否滿足callback函數,是則返回true,否則返回false
Array.prototype.some()
-
語法:arr.some(callback[, thisArg])
-
參數:
-
currentValue 當前值
-
currentIndex 當前值的位置
-
array 所操作的數組
-
callback 斷言數組內每個元素的callback函數
-
thisArg 可選 執行callback時作為this的值
-
返回:斷言數組內是否有元素滿足callback函數,是則返回true,否則返回false
Array.prototype.includes() ECMA7
-
語法:
-
arr.includes(searchElement)
-
arr.includes(searchElement, fromIndex)
-
參數:
-
-
searchElement 需要查找的元素
-
fromIndex 可選 指定開始查詢位置
-
返回:true,false
開唱:
如果你要對數組內容進行一些判斷,可以先不要想著用forEach,優先思考一下上面三個是否可以滿足你的需求。其中,every可以判斷數組內的內容是否全部滿足callback函數的條件,而some則可以判斷數組內是否有內容滿足callback函數的條件。 舉個慄子:
-
1 function isBigEnough(element, index, array) { 2 3 return element >= 10; 4 5 } 6 7 8 9 [12, 5, 8, 130, 44].every(isBigEnough); // false 10 11 [12, 5, 8, 130, 44].some(isBigEnough); // true
而includes方法則可以查找是否具體存在某一個元素,或者從某個具體的位置開始是否存在某個元素。但值得註意的是,includes方法是ECMA7中的標準,在使用之前需要確定運行環境是否支持此項方法。
-
1 var a = [1, 2, 3]; 2 3 a.includes(2); // true 4 5 a.includes(2, 1); // true 6 7 a.includes(2, 2); // false 8 9 a.includes(4); // false
數組內容的獲取 4個方法
Array.prototype.find() ECMA6
-
語法:arr.find(callback[, thisArg])
-
參數:
-
currentValue 當前值
-
currentIndex 當前值的位置
-
array 所操作的數組
-
callback 對數組內每個值執行的方法
-
thisArg 可選 執行callback時作為this的值
-
返回:第一個滿足callback條件的值
Array.prototype.findIndex() ECMA6
-
語法:arr.findIndex(callback[, thisArg])
-
參數:
-
currentValue 當前值
-
currentIndex 當前值的位置
-
array 所操作的數組
-
callback 對數組內每個值執行的方法
-
thisArg 可選 執行callback時作為this的值
-
返回:滿足callback條件的位置,沒有則返回-1
Array.prototype.indexOf()
-
語法:arr.indexOf(searchElement[, fromIndex])
-
參數:
-
-
searchElement 需要查找的元素
-
fromIndex 可選 指定查詢位置
-
返回:查到的第一個元素在數組內的位置,沒有返回-1
Array.prototype.lastIndexOf()
-
語法:arr.lastIndexOf(searchElement[, fromIndex])
-
參數:
-
-
searchElement 需要查找的元素
-
fromIndex 可選 指定查詢位置
-
返回:查到的最後一個元素在數組內的位置,沒有返回-1
開唱:
這一組方法和數組內容判斷的一組有些相似,只不過,數組內容判斷的方法返回的都是true或者false,而這一組方法都會返回具體的值。 find方法會返回滿足你條件的第一個元素,而findIndex會返回滿足你條件的第一個元素的位置。而indexOf、lastIndexOf方法則和includes方法很相似,只不過前兩個返回的是具體的位置,includes返回的是布爾值。 舉個慄子:
-
1 function isBigEnough(element) { 2 3 return element >= 15; 4 5 } 6 7 8 9 console.log([12, 5, 8, 130, 5, 44].find(isBigEnough)); // 130 10 11 console.log([12, 5, 8, 130, 5, 44].findIndex(isBigEnough)); // 3 12 13 console.log([12, 5, 8, 130, 5, 44].indexOf(5)); // 1 14 15 console.log([12, 5, 8, 130, 5, 44].lastIndexOf(5)); // 4 16 17 console.log([12, 5, 8, 130, 5, 44].some(isBigEnough)); // true 18 19 console.log([12, 5, 8, 130, 5, 44].every(isBigEnough)); // false 20 21 console.log([12, 5, 8, 130, 5, 44].includes(5,4)); // true
數組的構造 6個方法
Array.from() ECMA6
-
語法:Array.from(arrayLike[, mapFn[, thisArg]])
-
參數:
-
arrayLike 具有長度屬性和有序元素的對象
-
mapFn 可選 對參數arrayLike執行的map函數
-
thisArg 可選 執行mapFn時作為this的值
-
返回:一個新的數組實例
Array.of() ECMA6
-
語法:Array.of(element0[, element1[, ...[, elementN]]])
-
參數:elementN 生成數組的元素
-
返回:一個新的數組實例
Array.prototype.concat()
-
語法:ar newarray = oldarray.concat(value1[, value2[, ...[, valueN]]])
-
參數:valueN 搭伙到原數組中的元素或數組
-
返回:一個新的數組實例
Array.prototype.filter()
-
語法:var newArray = arr.filter(callback[, thisArg])
-
參數:
-
currentValue 當前值
-
currentIndex 當前值的位置
-
array 所操作的數組
-
callback 斷言數組的每個元素是否滿足callback函數,返回true則保留元素,返回false則刪除元素
-
thisArg 可選 執行callback時作為this的值
-
返回:一個新的數組實例
Array.prototype.map()
-
語法:var newArray = arr.filter(callback[, thisArg])
-
參數:
-
currentValue 當前值
-
currentIndex 當前值的位置
-
array 所操作的數組
-
callback 遍歷原數組元素生成新數組元素的函數
-
thisArg 可選 執行callback時作為this的值
-
返回:一個新的數組實例
Array.prototype.slice()
-
語法:
-
arr.slice()
-
arr.slice(begin)
-
arr.slice(begin, end)
-
參數:
-
begin 可選 淺拷貝的初始位置
-
end 可選 淺拷貝的結束位置
-
返回:一個新的數組實例
開唱:
在這一組中都是可以返回一個新數組,同時不會改變原數組的方法,因此把它們歸為數組的構造這一類,它們都可以構造出一個新的數組。
Array.from(),Array.of()是ES6中新增的方法。需要特別指出的是,Array.from(),Array.of()方法是靜態方法,只能通過Array對象來調用。
Array.from方法用於將兩類對象轉為真正的數組:類似數組的對象( array-like object )和可遍歷( iterable )的對象(包括 ES6 新增的數據結構 Set 和Map )。在此之前,我們習慣於使用Array.prototype.slice.call()這種方式,將類數組對象轉換為數組,如今我們有了更加直接的方法。
-
1 function f() { 2 3 return Array.from(arguments); 4 5 } 6 7 f(1, 2, 3); 8 9 // [1, 2, 3]
Array.of()方法則更加簡單,將若幹參數元素組成一個新的數組。
-
1 Array.of(1); // [1] 2 3 Array.of(1, 2, 3); // [1, 2, 3]
Array.prototype.concat()方法,既可以用於將目標數組和參數數組連接成為一個新數組,也可以實現類似於將參數元素按順序push進數組的效果。除了使用concat,也可以使用ES6中新增的擴展運算符(spread,也就是三個點...),實現合併數組的功能。
-
1 var arr1 = ['a', 'b']; 2 3 var arr2 = ['c']; 4 5 var arr3 = ['d', 'e']; 6 7 8 9 // ES5的合併數組 10 11 arr1.concat(arr2, arr3); 12 13 // [ 'a', 'b', 'c', 'd', 'e' ] 14 15 16 17 // ES6的合併數組 18 19 [...arr1, ...arr2, ...arr3] 20 21 // [ 'a', 'b', 'c', 'd', 'e' ]
通過Array.prototype.filter()方法的命名就可以看出,它實現了一個類似於過濾器的效果。滿足參數函數條件的元素將被過濾出來組成一個新的數組返回。
-
1 var myArr = [1,2,3,4,5]; 2 3 var result = myArr.filter(v=>v<3) 4 5 console.log(result) //[ 1, 2 ]
Array.prototype.map()方法有些類似於forEach方法。不同的是,forEach方法只是單純的迴圈遍曆數組,而map可以將迴圈遍歷後的結果組成一個新的數組返回。
-
1 var numbers = [1, 5, 10, 15]; 2 3 var doubles = numbers.map(x => x * 2); 4 5 console.log(doubles) //[ 2, 10, 20, 30 ]
Array.prototype.slice()方法實現數組的截取功能,可以指定開始結束位置,截取相應位置內的元素組成新的數組。
-
1 var a = ['zero', 'one', 'two', 'three']; 2 3 var sliced = a.slice(1, 3); 4 5 6 7 console.log(a); // ['zero', 'one', 'two', 'three'] 8 9 console.log(sliced); // ['one', 'two']
數組的改造
Array.prototype.copyWithin() ECMA6
-
語法:
-
arr.copyWithin(target)
-
arr.copyWithin(target, start)
-
arr.copyWithin(target, start, end)
-
參數:
-
target 拷貝到的目標位置
-
start 可選 拷貝內容起始位置
-
end 可選 拷貝內容結束位置
Array.prototype.fill() ECMA6
-
語法:
-
arr.fill(value)
-
arr.fill(value, start)
-
arr.fill(value, start, end)
-
參數:
-
value 填充數組的值
-
start 可選 填充起始位置
-
end 可選 填充結束位置
Array.prototype.pop()
-
語法:arr.pop()
-
返回:移除的元素
Array.prototype.push()
-
語法:arr.push([element1[, ...[, elementN]]])
-
參數:elementN 壓如數組尾部的元素
-
返回:數組的長度
Array.prototype.shift()
-
語法:arr.shift()
-
返回:移除的元素
Array.prototype.unshift()
-
語法:arr.unshift([element1[, ...[, elementN]]])
-
參數:elementN 壓如數組頭部的元素
-
返回:數組的長度
Array.prototype.reverse()
-
語法:arr.reverse()
-
返回:相反的數組
Array.prototype.sort()
-
語法:
-
array.sort()
-
arr.sort(compareFunction)
-
參數:
-
compareFunction 可選 定義排序規則的函數
-
返回:一個新的數組實例
Array.prototype.splice()
-
語法:
-
arr.splice(start)
-
arr.splice(start, deleteCount)
-
arr.splice(start, deleteCount, item1, item2, ...)
-
參數:
-
start 開始改變數組的位置
-
deleteCount 可選 刪除數組的數量
-
itemN 可選 插入數組的元素
-
返回:包含刪除元素的數組
開唱:
Array.prototype.copyWithin()和Array.prototype.fill()是ES6中新增的方法。Array.prototype.copyWithin()實現了數組內的拷貝,可以選定拷貝數據來源的開始結束位置,以及替換目標開始位置。Array.prototype.fill()則會將指定位置的數組元素全部替換為指定的值。
-
1 // 將3號位複製到0號位 2 3 [1, 2, 3, 4, 5].copyWithin(0, 3, 4) 4 5 // [4, 2, 3, 4, 5] 6 7 8 9 //從1號位開始,向原數組填充7,到2號位之前結束 10 11 ['a', 'b', 'c'].fill(7, 1, 2) 12 13 // ['a', 7, 'c']
這一組方法中,我們最熟悉的莫過於pop,push,shift,unshift這四個方法。其中pop,push是控制數組尾部元素進出的方法,而shift,unshift是控制數組頭部元素進出的方法。通過上面的方法我們可以通過數組模擬實現棧和隊列的效果。棧是先進後出,進棧使用push方法,出棧使用pop方法。隊列是先進先出,進隊列使用push方法,出隊列使用shift方法。
Array.prototype.reverse()方法可得到一個反轉的隊列,但它在返回反轉數組的同時,也改變的原數組的排列順序,這一點是需要註意的,因此將它歸入了數組的改造這一組當中。同樣Array.prototype.sort()也是用於數組排序的一個方法,不傳參數將根據元素的unicode進行排序,同樣會改變原數組的排列順序。
Array.prototype.splice()方法可以實現數組特定位置元素的插入,刪除。
-
1 var myArr = [1,2,3,4,5]; 2 3 // 刪除3號位元素 4 5 myArr.splice(2,1) //[ 1, 2, 4, 5 ] 6 7 // 在第3號位元素的位置插入元素3 8 9 myArr.splice(2,0,3) //[ 1, 2, 3, 4, 5 ] 10 11 // 刪除第4號位及後面的元素 12 13 myArr.splice(3) //[ 1, 2, 3 ] 14 15 // 第4號位元素位置插入元素4,5 16 17 myArr.splice(3,0,4,5) //[ 1, 2, 3, 4, 5 ]
數組的遍歷
Array.prototype.forEach()
-
語法:arr.forEach(function callback(currentValue, index, array) { //your iterator }[, thisArg]);
-
參數:
-
currentValue 當前處理的元素
-
index 當前元素的位置
-
array 當前處理的數組
-
callback 對每個元素遍歷執行的方法
-
thisArg 執行callback時的this值
-
返回:undefined
Array.prototype.keys() ECMA6
-
語法:arr.keys()
-
返回:數組迭代器對象
Array.prototype.values() ECMA6
-
語法:arr.values()
-
返回:數組迭代器對象
Array.prototype.entries() ECMA6
-
語法:arr.entries()
-
返回:數組迭代器對象
開唱:
相信大部分人對Array.prototype.forEach()這個數組方法並不陌生,它對數組元素遍歷執行回調方法,這裡不做過多介紹。Array.prototype.entries(),Array.prototype.keys()和Array.prototype.values()是ES6中新增的三個數組方法,用於遍曆數組。它們都返回一個遍歷器對象,可以用for...of迴圈進行遍歷,唯一的區別是keys()是對鍵名的遍歷、values()是對鍵值的遍歷,entries()是對鍵值對的遍歷。
-
1 for (let index of ['a', 'b'].keys()) { 2 3 console.log(index); 4 5 } 6 7 // 0 8 9 // 1 10 11 12 13 for (let elem of ['a', 'b'].values()) { 14 15 console.log(elem); 16 17 } 18 19 // 'a' 20 21 // 'b' 22 23 24 25 for (let [index, elem] of ['a', 'b'].entries()) { 26 27 console.log(index, elem); 28 29 } 30 31 // 0 "a" 32 33 // 1 "b"
數組的累加
Array.prototype.reduce()
-
語法:arr.reduce(callback[, initialValue])
-
參數:
-
accumulator 累加值
-
currentValue 當前值
-
currentIndex 當前值的位置
-
array 所操作的數組
-
callback 累加器
-
initialValue 可選 初始值
-
返回:累加器最終計算結果
Array.prototype.reduceRight()
-
語法:arr.reduceRight(callback[, initialValue])
-
參數:
-
accumulator 累加值
-
currentValue 當前值
-
currentIndex 當前值的位置
-
array 所操作的數組
-
callback 累加器
-
initialValue 可選 初始值
-
返回:累加器最終計算結果
開唱:
Array.prototype.reduce()和Array.prototype.reduceRight()方法都接收一個函數作為累加器,數組中的每個值(reduce從左到右,reduceRight從右到左)開始縮減,最終為一個值。相比與forEach、map等數組方法,reduce不必再另外定義一個變數存儲最終計算結果,更加方便。另外,通過觀察,不難發現一個規律,除了Array.prototype.reduce()和Array.prototype.reduceRight()方法,其他有callback回調參數的方法中,其callback回調函數中的參數都是包含三個參數的:當前值currentValue,當前值的位置currentIndex,所操作的數組array;而Array.prototype.reduce()和Array.prototype.reduceRight()方法則包含四個,多了一個累加值作為第一個參數。
-
1 var total = [0, 1, 2, 3].reduce(function(sum, value) { 2 3 return sum + value; 4 5 }, 0); 6 7 // total is 6
數組轉字元串
Array.prototype.toString()
-
語法:arr.toString()
-
返回:數組的字元串表示
Array.prototype.toLocaleString()
-
語法:
-
arr.toLocaleString();
-
arr.toLocaleString(locales);
-
arr.toLocaleString(locales, options);
-
參數:
-
locales BCP 47語言標簽字元串
-
options 可選 配置參數對象
-
返回:數組的字元串表示
Array.prototype.join()
-
語法:
-
arr.join()
-
arr.join(separator)
-
參數:separator 可選 分割符
-
返回:數組的字元串表示
開唱:
我們時常會遇到數組與字元串之間的轉換。根據上面學到的知識,將字元串轉換為數組,除了字元串的方法,我們還可以使用數組的Array.from()方法。而將數組轉換為字元串,則可以使用上面的三個方法。其中Array.prototype.toString()方法可以將數組直接轉換為字元串的表示形式。Array.prototype.toLocaleString()方法可以根據參數將數組的字元串表示本地化,但支持的情況並不是很好,因此不用過多考慮。Array.prototype.join()方法可以指定數組轉換為字元串的分隔符。
-
1 var months = ['Jan', 'Feb', 'Mar', 'Apr']; 2 3 months.toString(); // "Jan,Feb,Mar,Apr" 4 5 months.join('-'); // "Jan-Feb-Mar-Apr"
那位說,聽你說了這麼多,也沒見什麼演唱會啊,那下麵就讓我們真正的唱一段。
判斷是不是數組,isArray最靠譜。
按照條件來判斷,every/some給答案
是否包含此元素,includes最快速。
find/findIndex很相似,按條件給第一個值。
indexOf/lastIndexOf也很強,有沒有來在哪忙。
from和of,都能用來生數組。
concat當紅娘,數組結婚她幫忙。
filter瘦身有一套,不想要的都不要。
map整容有實力,改頭換面出新意。
slice就像買切糕,想切哪來就下刀。
自力更生很重要,copyWithin自己搞。
fill就像填大坑,想往哪扔往哪扔。
搬山摸金四兄弟,pop、push、shift、unshift不難記。
造反其實很容易,reverse一下看好戲。
sort排序有技巧,能小大來能大小。
splice要認識,能插能刪有本事。
forEach最熟悉,有人說它是萬能滴。
keys、values、entries,遍曆數組新方式。
算總賬,不要慌,reduce、reduceRight幫你忙。
toString,join變字元,toLocaleString不常用。
當里個當,當里個當,數組32方法,猥瑣發育不要浪,嘿!不要浪!
如果你喜歡我們的文章,關註我們的公眾號和我們互動吧。