寄語:
JS數組的方法很是的豐富和瑣碎,學習和使用過程當中老是須要反覆的記憶、查看文檔,但做爲JS基礎這樣真的不該該,咱們應該把它記得倒背如流,深刻理解纔對。
可是要怎樣才能作到呢?這正是我也本文的初衷,根據我的的經驗總結了一下,但願可以幫助和我同樣困惑的人,搞定這個頭疼的問題。node
數組的建立有三種方式:構造函數方式、字面量方式、ES6新增的Array.of()方法建立。數組
構造函數方式:bash
let arr = new Array(); // 建立一個空數組
let arr = new Array(10); // 建立長度爲10的數組
let arr = new Array('a'); // 建立包含一個字符串元素a的數組
let arr = new Array(10, 'a'); // 建立包含10和字符串a兩個元素的數組
複製代碼
小結:
1.new 關鍵字是可省略的
2.當只傳一個number類型參數時,建立的是參數指定長度的數組。即構造函數形式建立數組,不能建立只包含一個number類型元素的數組app
字面量方式:函數
let arr = [10, 'a']; // 字面量方式,即直接給數組賦值
複製代碼
Array.of()方法(ES6新增):
方法的做用是將一組值(即傳進來的參數)轉換爲數組。
這個方法彌補了構造函數建立數組的不足。能夠實現建立只有一個number類型元素的數組。學習
let arr = Array.of(3);
console.log(arr); // [3]
// 參數能夠是各類類型
let arr1 = Array.of(1, 'a', true, null, undefined, {name: "zhangsan"}, [45]);
console.log(arr1); // [ 1, 'a', true, null, undefined, { name: 'zhangsan' }, [ 45 ] ]
複製代碼
兩種較爲準確的檢測方法:ui
let arr = [1, 2];
arr.length = 1;
console.log(arr); // [1]
arr.length = 3;
console.log(arr); // [1, , ]
複製代碼
JavaScript的數組方法包括數組原型的方法、構造函數的方法(ES6新增部分)
針對每個方法咱們主要了解四個方面:做用、參數、返回值、原數組是否改變
(一). 原型上的方法this
push():
做用:向數組的末尾添加一項或多項
參數:ele1[, ele2[, ...[, elen]]]
返回值:添加元素後數組的長度
原數組是否改變:是編碼
let arr = [1, 2, 3];
let temp = arr.push('a', 'b');
console.log(arr, temp); // [1, 2, 3, 'a', 'b'] 5
複製代碼
pop():
做用:刪除數組最後一項
參數:無
返回值:刪除的那一項
原數組是否改變:是spa
let arr = [1, 2, 3];
let temp = arr.pop();
console.log(arr, temp); // [1, 2] 3
複製代碼
unshift():
做用:向數組開頭添加一項或多項
參數:ele1[, ele2[, ...[, elen]]]
返回值:添加元素後數組的長度
原數組是否改變:是
let arr = [1, 2, 3];
let temp = arr.unshift('a', 'b');
console.log(arr, temp); // ['a', 'b', 1, 2, 3] 5
複製代碼
shift():
做用:刪除數組第一項
參數:無
返回值:刪除的那一項
原數組是否改變:是
let arr = [1, 2, 3];
let temp = arr.shift();
console.log(arr, temp); // [2, 3] 1
複製代碼
splice():
做用:刪除、插入、替換數組項
參數:startIndex[, deleteCount[, item1[, ...[, itemN]]]]
返回值:刪除項組成的數組
原數組是否改變:是
let arr = [1, 2, 3];
// 插入元素
let temp = arr.splice(1, 0, 'a', 'b'); // 在索引1的位置插入元素'a'和'b'
console.log(arr, temp); // [1, 'a', 'b', 2, 3] []
// 刪除元素
let temp1 = arr.splice(1, 2); // 刪除從索引1的位置開始的2項
console.log(arr, temp1); // [1, 2, 3] ['a', 'b']
// 替換一個元素
let temp2 = arr.splice(1, 1, 'a'); // 將索引1的位置的元素替換爲'a'
console.log(arr, temp2); // [1, 'a', 3 ] [2]
// 替換多個元素
let temp3 = arr.splice(0, 2, 'b', 'c'); // 將索引0的位置開始的兩項,替換成’b‘和’c‘
console.log(arr, temp3); // [’b‘, 'c', 3] [1, 'a']
// 只傳第一個參數,則刪除從第一個參數指定的位置到數組結尾的全部項
let temp4 = arr.splice(0); //從索引0的位置開始,刪除後面的全部項
console.log(arr, temp4); // [] [’b‘, 'c', 3]
複製代碼
copyWithin()
做用:將數組指定位置(start到end)的元素複製到當前數組的其餘位置(target開始),這種複製會替換原位置的元素(ES6新增)
參數說明:target[,start[,end]]
參數說明:
返回值:複製替換以後的數組
原數組是否改變:是
let arr = [1, 2, 3, 4, 5];
// 用索引0~4範圍內的元素,替換索引3~4範圍內的元素,由於要替換的位置只有兩個,因此只將4,5替換爲了1,2
let temp = arr.copyWithin(3);
console.log(arr, temp); // [1, 2, 3, 1, 2] [1, 2, 3, 1, 2]
let arr1 = [1, 2, 3, 4, 5];
// 用索引2~4範圍內的元素,替換索引3~4範圍內的元素,由於要替換的位置只有兩個,因此只將4,5替換爲了3,4
let temp1 = arr1.copyWithin(3, 2);
console.log(arr1, temp1); // [1, 2, 3, 3, 4] [1, 2, 3, 3, 4]
複製代碼
小結:
總結上述的描述,copyWithin的做用就是在數組長度的範圍內,複製start(包括)到end(不包括)範圍內的元素,而後用上述的元替換掉從target(包括)開始到數組結尾的元素,能替換多少就替換多少
reverse():
做用:翻轉原數組
參數:無
返回值:翻轉後的數組
原數組是否改變:是
let arr = [1, 2, 3];
let temp = arr.reverse();
console.log(arr, temp); // [ 3, 2, 1 ] [ 3, 2, 1 ]
複製代碼
sort():
做用:數組排序
參數:compareFunction
參數說明:
返回值:排序後的數組
原數組是否改變:是
// 數組從小到大排序
let arr = [1, 4, 6, 7, 8, 3, 2];
let temp = arr.sort((a, b) => {
return a - b;
})
console.log(arr, temp); // [ 1, 2, 3, 4, 6, 7, 8 ] [ 1, 2, 3, 4, 6, 7, 8 ]
// 一個實用的數組排序的例子,根據對象元素的排序,排序對象在數組中的位置
let objArr = [{id: 3, name: "lilei"},{id: 1, name: "hanmeimei"},{id: 2, name: "yimi"}];
let tempArr = objArr.sort((a, b) => {
// 按照id從小到大的順序,對數組中的對象進行排序
// 這個示例說明回調函數的形參a,b實際就是數組中當前進行比對的兩個元素
return a.id - b.id;
});
console.log(objArr); // [{id: 1, name: 'hanmeimei'}, {id: 2, name: 'yimi'}, { id: 3, name: 'lilei' }]
console.log(tempArr); // [{id: 1, name: 'hanmeimei'}, {id: 2, name: 'yimi'}, { id: 3, name: 'lilei'}]
複製代碼
concat():
做用:基於當前的數組拼接數組
參數:value1[, value2[, ...[, valueN]]
參數說明:
返回值:拼接後的數組
原數組是否改變:否
let arr = [1,2];
let temp = arr.concat('a', {id:1}, ['lilei', 'hanmeimei']);
console.log(arr, temp); // [ 1, 2 ] [ 1, 2, 'a', { id: 1 }, 'lilei', 'hanmeimei']
// 用於複製數組
let arr = [1, 2];
let temp = arr.concat();
console.log(arr, temp); // [ 1, 2 ] [ 1, 2 ]
複製代碼
slice():
做用:基於當前數組的一項或多項建立一個新的數組
參數:startIndex[,endIndex]
參數說明:返回的元素包含startIndex位置的元素,但不包括endIndex位置的元素
返回值:返回截取的元素組成的數組
原數組是否改變:否
let arr = [0, 1, 2, 3, 4];
let temp = arr.slice(1,3); // 返回從索引1(包括)位置到索引3(不包括)位置以前的元素
console.log(arr, temp); // [0, 1, 2, 3, 4] [1, 2]
// 用於複製數組
let arr = [0, 1, 2, 3, 4];
let temp = arr.slice(0); // 返回從索引0(包括)位置到數組結尾的全部元素
console.log(arr, temp); // [0, 1, 2, 3, 4] [0, 1, 2, 3, 4]
複製代碼
indexOf():
做用:從數組開頭查找元素在數組中的索引位置(ES5的方法)
參數:searchElement[, fromIndex]
返回值:searchElement在數組中的索引,沒找到searchElement則返回-1
原數組是否改變:否
let arr = [1, 2, 3, 4, 5, 6, 2];
// 從數組開頭開始查找
let temp = arr.indexOf(2);
console.log(arr, temp); // [ 1, 2, 3, 4, 5, 6, 2 ] 1
// 從指定的位置開始查找
let temp1 = arr.indexOf(2,3); // 從索引3(包括)的位置向後查找元素2
console.log(arr, temp1); // [ 1, 2, 3, 4, 5, 6, 2 ] 6
複製代碼
lastIndexOf():
做用:從數組結尾查找元素在數組中的索引位置(ES5的方法)
參數:searchElement[, fromIndex]
返回值:searchElement在數組中的索引,沒找到searchElement則返回-1 原數組是否改變:否
let arr = [1, 2, 3, 4, 5, 6, 2];
// 從數組末尾開始查找
let temp = arr.lastIndexOf(2);
console.log(arr, temp); // [ 1, 2, 3, 4, 5, 6, 2 ] 6
// 從指定的位置開始查找
let temp1 = arr.lastIndexOf(2,3); // 從索引3(包括)的位置向前查找元素2
console.log(arr, temp1); // [ 1, 2, 3, 4, 5, 6, 2 ] 1
複製代碼
every():
做用:對數組中的每一項運行給定函數,若是該函數對每一項都返回true,則返回true(ES5方法)
參數:callback[, thisArg]
參數說明:callback有三個參數item(當前項),index(當前項索引),array(數組對象自己)
返回值:true 或 false
原數組是否改變:涉及callback,所以不肯定,具體詳情見下文中的原型方法的小結部分。
let arr = [1, 2, 3, 4];
let temp = arr.every((item, index, array) => {
return item > 2;
});
console.log(arr, temp); // [ 1, 2, 3, 4 ] false
// 方法的第二個參數可選,做用是設定第一個參數中的this指向,若是使用第二個參數,注意callback不能是箭頭函數
// 後面的迭代方法涉及此參數的,用法相同,不在贅述
let arr = [1, 2, 3, 4];
let temp = arr.every(function(item, index, array) {
return item > this.id;
}, {id: 2});
console.log(arr, temp); // [ 1, 2, 3, 4 ] false
複製代碼
some():
做用:對數組中的每一項運行給定函數,若是該函數對任意一項返回true,則返回true(ES5方法)
參數:callback[, thisArg]
參數說明:callback有三個參數item(當前項),index(當前項索引),array(數組對象自己)
返回值:true 或 false
原數組是否改變:涉及callback,所以不肯定,具體詳情見下文中的原型方法的小結部分。
let arr = [1, 2, 3, 4];
let temp = arr.some((item, index, array) => {
return item > 2;
});
console.log(arr, temp); // [ 1, 2, 3, 4 ] true
複製代碼
filter():
做用:對數組中的每一項運行給定函數,返回該函數返回true的項組成的數組(ES5方法)
參數:callback[, thisArg]
參數說明:callback有三個參數item(當前項),index(當前項索引),array(數組對象自己)
返回值:函數返回true的項組成的數組
原數組是否改變:涉及callback,所以不肯定,具體詳情見下文中的原型方法的小結部分。
let arr = [1, 2, 3, 4];
let temp = arr.filter((item, index, array) => {
return item > 2;
});
console.log(arr, temp); // [ 1, 2, 3, 4 ] [3, 4]
複製代碼
map():
做用:對數組中的每一項運行給定函數,返回每次函數調用的結果組成的數組(ES5方法)
參數:callback[, thisArg]
參數說明:callback有三個參數item(當前項),index(當前項索引),array(數組對象自己)
返回值:函數每次調用結果組成的數組
原數組是否改變:涉及callback,所以不肯定,具體詳情見下文中的原型方法的小結部分。
let arr = [1, 2, 3, 4];
let temp = arr.map((item, index, array) => {
return item * item;
});
console.log(arr, temp); // [ 1, 2, 3, 4 ] [ 1, 4, 9, 16]
複製代碼
forEach():
做用:對數組中的每一項運行給定函數。無返回值(ES5方法)
參數:callback[, thisArg]
參數說明:callback有三個參數item(當前項),index(當前項索引),array(數組對象自己)
返回值:無
原數組是否改變:涉及callback,所以不肯定,具體詳情見下文中的原型方法的小結部分。
let arr = [1, 2, 3, 4];
let temp = arr.forEach((item, index, array) => {
// 不會有返回值,但可在這裏執行某些操做
return item * item;
});
console.log(arr, temp); // [ 1, 2, 3, 4 ] undefined
複製代碼
注意:
forEach在全部項都遍歷完成以前,沒法像for循環同樣提早終止循環
reduce():
做用:從數組的第一項開始,逐步遍歷到最後,迭代數組的全部項(ES5方法)
參數:callback[, initialValue]
參數說明:
返回值:數組迭代後,總體的迭代結果
原數組是否改變:涉及callback,所以不肯定,具體詳情見下文中的原型方法的小結部分。
// 數組求和
let arr = [1, 2, 3];
let sum = arr.reduce((prev, cur, index, array) => {
return prev + cur;
});
console.log(arr, sum); // [ 1, 2, 3 ] 6
// 傳initialValue 基礎值的示例
let sum1 = arr.reduce((prev, cur, index, array) => {
return prev + cur;
}, 10);
// 返回的值是:10+1+2+3
console.log(arr, sum1); // [ 1, 2, 3 ] 16
複製代碼
reduce源碼的實現:
Array.prototype.myReduce = function(callback, initialVal){ let prev = initialVal || this[0]; for(var i = pre ? 0 : 1; i < this.length; i++){ prev = callback(prev, this[i], i, this); } return prev } 複製代碼
reduceRight():
做用:從數組的最後一項開始,逐步遍歷到第一項,迭代數組的全部項(ES5方法)
參數:callback[, initialValue]
參數說明:
返回值:數組迭代後,總體的迭代結果
原數組是否改變:涉及callback,所以不肯定,具體詳情見下文中的原型方法的小結部分。
// 拼接字符串,從後向前迭代數組進行拼接
let arr = ['h', 'e', 'l', 'l', 'o'];
let str = arr.reduceRight((prev, cur, index, array) => {
return prev + cur;
});
console.log(arr, str); // [ 'h', 'e', 'l', 'l', 'o' ] 'olleh'
複製代碼
find():
做用:查找數組中第一個符合條件的元素,返回該元素 (ES6新增)
參數:callback[, thisArg]
參數說明:參數的使用同上述的forEach、every、map、some、filter方法一致
返回值:查找到則返回該元素,沒找到返回undefined
原數組是否改變:涉及callback,所以不肯定,具體詳情見下文中的原型方法的小結部分。
let arr = [1, 2, 3, 4, 5];
let temp = arr.find((item, index, array) => {
return item > 2;
})
console.log(arr, temp); // [1, 2, 3, 4, 5] 3
複製代碼
findIndex():
做用:查找數組中第一個符合條件的元素所在位置的索引,並返回該索引值
參數:callback[, thisArg]
參數說明:參數的使用同上述的forEach、every、map、some、filter方法一致
返回值:查找到則返回該索引值,沒找到返回-1
原數組是否改變:涉及callback,所以不肯定,具體詳情見下文中的原型方法的小結部分。
let arr = [1, 2, 3, 4, 5];
let temp = arr.findIndex((item, index, array) => {
return item > 2;
})
console.log(arr, temp); // [1, 2, 3, 4, 5] 2
複製代碼
fill():
做用:用指定元素,填充數組從start(包括)到end(不包括)之間的元素,若是該區間內已經有元素,直接替換掉(ES6新增)
參數:value[, start[, end]]
返回值:填充後的數組
原數組是否改變:是
let arr = [1, 2, 3, 4, 5];
let temp = arr.fill('a', 2, 4);
console.log(arr, temp); // [1, 2, 'a', 'a', 5] [1, 2, 'a', 'a', 5]
複製代碼
includes():
做用:判斷數組中是否包含指定的元素(ES7新增)
參數:searchElement[, fromIndex]
返回值:true或false
原數組是否改變:否
let arr = [1, 2, 3, 4, 5];
let temp = arr.includes(5);
console.log(arr, temp); // [1, 2, 3, 4, 5] true
// 這個方法彌補了indexOf查看元素時的一個不足,即查找NaN的偏差
let arr1 = [NaN, 'a'];
let temp1 = arr1.includes(NaN);
let temp2 = arr1.indexOf(NaN);
console.log(temp1, temp2); // true -1
複製代碼
toString()、toLocalString():
做用:調用數組每一項的toString()方法,返回的是以逗號分隔的字符串
參數:無
返回值:轉化後的字符串
原字數組是否改變:否
let arr = [1, [1, 2, [4]], {name: "zhangsan"}, 3];
let temp = arr.toString();
console.log(arr); [ 1, [ 1, 2, [ 4 ] ], { name: 'zhangsan' }, 3 ]
console.log(temp); // '1,1,2,4,[object Object],3'
複製代碼
join():
做用:將數組元素轉化爲字符串(調用每一個元素的toString方法),並使用指定的分隔符(默認爲逗號)進行拼接,返回拼接後的字符串
參數:分隔符,默認爲逗號(,)
返回值:拼接後的字符串
原數組是否改變:否
let arr = [1, [1, 2, [4]], {name: "zhangsan"}, 3];
let temp = arr.join();
console.log(arr); [ 1, [ 1, 2, [ 4 ] ], { name: 'zhangsan' }, 3 ]
console.log(temp); // '1,1,2,4,[object Object],3'
// 數組求和
let arr1 = [1, 2, 3];
console.log(eval(arr1.join('+'))); // 6
複製代碼
原型方法的總結:
1. 數組的方法無外乎是對數組的增刪改查、轉換、迭代。增、刪、改都會改變原有的數組,查、轉換的方法不涉及callback參數的不會改變原數組,涉及到的則視狀況而定,迭代方法由於均涉及到callback參數,所以也不肯定。
那麼爲何涉及到callback就不肯定了呢???
首先若是直接在callback中操做原數組,那確定原數組會改變。例如:let arr = [1,2,3,4]; let temp = arr.forEach((item,index,array) => { // 直接經過索引操做原數組 array[index] *= item; }); console.log(arr,temp); // [1, 4, 9, 16] undefined 複製代碼
若是不是直接操做原數組,而是操做callback的item參數的時,若是item是基本數據類型則原數組中對應的該項元素不會改變,若是是引用類型(數組,對象、函數等)則改變,由於操做引用類型的值,實質是操做該值所在存貯地址的內容,而item對應的原數組中的元素和item是同一引用地址,所以會致使原數組中對應元素改變。(小夥伴們對這裏若是仍是不理解,能夠看下數組方法polyfill的實現,這裏再也不贅述)
2. 全部涉及索引的方法,開始位置都是在操做範疇的,結束位置都是不包括在操做範圍內的
(二).構造函數的方法
Array.from():
做用:將類數組轉化爲數組
參數:arrayLike[, mapFn[, thisArg]]
參數說明:
返回值:轉化後的數組,若是有mapFn,則返回結果是通過mapFn處理的數組
原類數組是否改變:不使用mapFn,則類數組不改變。使用mapFn則結果同上述迭代方法中使用callback的狀況一致。
let str = 'hello';
let temp = Array.from(str);
console.log(str, temp); // hello [ 'h', 'e', 'l', 'l', 'o' ]
let temp1 = Array.from(str, (item, index) => {
return item.toUpperCase();
});
console.log(str, temp1); // hello [ 'H', 'E', 'L', 'L', 'O' ]
複製代碼
小結:
Array.from() 等價於 Array.prototype.slice.call(arguments,0)
數組的擴展運算符能夠將數組轉化爲以逗號分割的參數序列。
幾個簡單使用的應用場景:
let arr = [1, 2, 3];
// apply寫法
Math.min.apply(null, arr)
// 擴展運算符寫法
Math.min(...arr)
複製代碼
let arr1 = [2, 3, 4];
let arr2 = ['a', 'b', 'c'];
// 拼接數組arr1和arr2
console.log([...arr1, ...arr2]); // [2, 3, 4, 'a', 'b', 'c']
複製代碼
[…'hello'] // [ 'h', 'e', 'l', 'l', 'o' ]
複製代碼
長篇大論了這麼久,不是爲了重複書中或者官方的使用說明。而是再分享一些學習的思路,讓初學者可以更快更準的掌握JavaScript數組,讓停留在會用層次的同窗瞭解它更多。 但願我上述的方法說明可以讓你對JavaScript數組一目瞭然,在各個方法所闡述的幾個方面的對比中,將它更輕易的記住。